20181217

web 安全   XSS  CSP CSRF 点击劫持  OAuth cdn

/*
* xss 攻击预防
* 目前地址栏的xss : http://xxx.html?name=<script>alert(1)</script>
* 输入框,图片,富文本
* chrome 会自己转义
*
* */

// 转义 < > " '  空格不转义
function escapeHtml (str) {
  if(!str) return '';
  // 地址栏的xss已经先被chrome 转义了,这代码无效了
  str = str.replace(/&/g, '&amp;')
  str = str.replace(/</g, '&lt;')
  str = str.replace(/>/g, '&gt;')
  str = str.replace(/"/g, '&quto;')
  str = str.replace(/'/g, '&#39;') // html实体
  return str
}
// js 转义
// 地址栏的xss已经先被chrome 转义了,这代码无效了
// let url = JSON.stringify(xx),

/*
* 富文本xss 过滤
* 黑名单过滤
* 白名单允许
* 插件 npm i xss
*
*
* */
// 富文本过滤
function filter (str) {
  if(!str) return '';
  // 黑名单过滤太多太麻烦
  str = str.replace(/<\s*\/?script\s*>/g,'');   // 过滤 <script>
  str = str.replace(/javascript:[^'"]*/g,'');   // 过滤 javascript:alert(1)
  str = str.replace(/onerror\s*=\s*['"]?[^'"]*['"]?/g,'');   // 过滤 onerror

  return str;
}
// cheerio 解析html, 语法类似 jq
function filter2 (html) {
  if(!html) return '';
  var cheerio = require('cheerio'); // 引入 cheerio
  var $ = cheerio.load(html)
  // 白名单
  var whiteList = {
    'img':['src'],
    'font':['color','size'],
    'a':['href']
  }
  $('*').each(function (index, elem) {
    if(!whiteList[elem.name]){  // 清空白名单不存在的标签
      $(elem).remove();
      return;
    }
    for(var attr in elem.attribs){
      if(whiteList[elem.name].indexOf(attr)===-1){
        $(elem).attr(attr,null) // 清空白名单不存在属性
      }
    }
  })
}

// npm i xss  使用第三方库解决白名单


/*
* csp  内容安全策略,用于指定哪些内容可执行
* 预防xss 攻击
*
*  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
*    详见 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP
* */


// nodejs 防xss
// ctx.set('X-XSS-Protection',1);  // 0是关闭 1是打开防御  功能不全面
//
// ctx.set(`Content-Security-Policy`,`default-src 'self'`)  //csp内容安全策略

/*
*  CSRF: 第三方网站不用访问你的网站,就拿到你的信息,并调用你的接口乱来
*
*  打开某网站A,自己的账号信息保存在cookie中被获取,导致自己银行卡的钱丢了
*  1.设置cookie只能本网站访问
*   cookie.set(sameSite = Strict)
*
*  2.加图形验证码/TOKEN等,必须经过本网站,防CSRF
*  nodejs npm i ccap 生成图形验证码
*
*  3.加 token ,必须经过本网站,防CSRF,  token的用户体验比图形验证码好
*
*  4. referer 不是很好,有些访问没有referer
*  验证referer值 禁止来自第三方网站的请求
*  // nodejs
*  var referer = ctx.reques.headers.referer;
*  if(!/^https?:\/\/localhost/.test(referer)){
*     console.log('error')
*  }
* */

// nodejs:  npm i crypto 加密

/*
*  点击劫持:原理:自己的网站被第三方用Iframe内嵌,
 *  自己点击跳出来的网站后,发现自己的钱没了。
*  垃圾邮件点击劫持
*  本网站禁止内嵌,防止点击劫持
*  nodejs  ctx.set('X-Frame-Options','DENY');  禁止页面内嵌  兼容ie8
* */
// 如果有iframe嵌入的话,两者值不一致,一刷新假页面,页面会跳转到真正的页面
// 如果被禁止js 则以下代码无效了
if(top.location !==window.location){
  top.location = window.location
}

// <iframe sandbox = '' >  iframe 的sandbox 可以禁用 js 等一堆功能

// http协议 窃听,篡cuan改
//    生成ca证书,放入项目中,引用ca证书,使用https来访问,proxy代理抓包则看不到任何请求数据

/*
* 密码 md5等加密  mysql 注入  文件上传漏洞(后端文件内容检查、用nginx读取文件再返回、控制读写权限等,nodejs问题不大)
* */
// 防止盗QQ,盗身份证进信息等   OAuth 引入  使用QQ登陆某网站,使用了用户授权

// cdn 加速 防dns攻击 https加密  token 时间戳, 签名
View Code

 es6

let {sin, cos} = Math  // 取出对应的参数
console.log(sin(30))

/**
 * 参数默认值
 * @param name
 */
function f1 (name = 'kang') {
  console.log(name)
}

f1()

/**
 * 扩展运算符
 * @param a
 * @param param
 */
function f2 (a, ...param) {
  console.log(param)   // [2,3,4,5,6,7]
}

f2(1, 2, 3, 4, 5, 6, 7)

// 合并数组
let arr1 = [1, 2, 3]
let arr2 = [4, 5, 6]
let arr3 = [...arr1, ...arr2]
console.log(arr3)

/*
* 箭头函数不能new 不能使用 arguments 可用 rest代替, 箭头函数中的this取决于函数的定义
* */
function Person () {

}
Person.name=123 // 静态属性  通过类名直接访问
View Code

 分页   固定内容高 offsetHeight +滚动top scrollTop >= 实际高 scrollHeight

  offsetWidth实际获取的是盒模型(width+border + padding)
offsetHeight内容的高(内容高+padding+border)
<template>
  <div>
    <div class="list" @scroll.passive="scrollData" ref="scrollOut">
      <p class="a" v-for="(val,key) in list" :key="key">{{val.id}}/{{val.name}}</p>
    </div>
  </div>
</template>

<script>
  export default {
    data () {
      return {
        list: [
          {id: 1, name: 'aa'},
          {id: 1, name: 'aa2'},
          {id: 1, name: 'aa3'},
          {id: 1, name: 'aa4'},
          {id: 1, name: 'aa5'},
          {id: 1, name: 'aa6'},
          {id: 1, name: 'aa7'},
          {id: 1, name: 'aa8'},
          {id: 1, name: 'aa9'},
          {id: 1, name: 'aa10'},
          {id: 1, name: 'aa11'},
        ],
        canLoad: true
      }
    },
    created () {
      document.title = '首页'
    },
    methods: {
      /*
      * offsetWidth实际获取的是盒模型(width+border + padding)
        offsetHeight内容的高(内容高+padding+border)

        固定内容高 offsetHeight +滚动top  scrollTop   >=   实际高 scrollHeight

      * */
      scrollData () {
        let outH = this.$refs.scrollOut.scrollHeight,
          currentH = this.$refs.scrollOut.offsetHeight,
          offH = this.$refs.scrollOut.scrollTop
        console.log('curr',currentH,offH,'out',outH)
        if (currentH + offH >= outH && this.canLoad) {
          this.fetchUser()
        }
      },
      fetchUser () {
        console.log('push')
        this.list.push({
          id: 2,
          name: 222
        })
        this.canLoad=false
      }
    }
  }

</script>

<style lang="less" scoped>
  .list {
    overflow-y: scroll;
    max-height: 200px;
  }

  .a {
    line-height: 30px;
    font-size: 16px;
  }
</style>
View Code

基本数据类型:栈内存

函数柯里化

在一个函数中,首先填充几个参数,然后再返回一个新的函数的技术,称为函数的柯里化。通常可用于在不侵入函数的前提下,为函数 预置通用参数,供多次重复调用。

const add = function add(x) {
    return function (y) {
      return x + y
    }
  }

  const myadd = add(2)
  console.log(myadd(10))  //  多次调用 
  console.log(myadd(20))  // 多次调用 

数组去重:  [...new Set([1,2,2,3,4,4,5])]   // [1,2,3,4,5]

重绘:元素改颜色等样式不影响布局,重绘元素,损耗不大

回流:元素尺寸、结构变了,浏览器会重新渲染页面,称回流。   回流必重绘。   

** 避免频繁操作样式,可汇总后统一 一次修改,把 DOM 离线后修改,比如:先把 DOM 给 display:none (有一次 Reflow),然后你修改 100 次,然后再把它显示出来

页面初次渲染
浏览器窗口大小改变
元素尺寸、位置、内容发生改变
元素字体大小变化
添加或者删除可见的 dom 元素
激活 CSS 伪类(例如::hover)
查询某些属性或调用某些方法
clientWidth、clientHeight、clientTop、clientLeft
offsetWidth、scrollWidth、
getComputedStyle()
getBoundingClientRect()
scrollTo()

内存泄露:  定时器未清除、闭包变量

XSS: 地址栏加代码,转义

 CSRF: 第三方网站不用访问你的网站,就拿到你的信息,  加图片验证码、加 token等

点击劫持:网站 被iframe, 禁止iframe   js 判断 top.location!== window.location    两者要等才对

节流:scroll事件,resize窗口大小调整事件, 设置一个时间,时间到了,执行scroll 回调,这个时间内触发的scroll事件,被忽略

防抖:scroll事件,用户操作频繁,只认停止操作最后一次scroll事件,还是需要设置一个等待时间

apply call   bind

  let round = {
    pi: 3.14,
    area: function (r) {
      return this.pi * r * r
    }
  }
  console.log(round.area(2))
  // pi改为3.14159   // 传个object 来改变this的指向
  console.log(round.area.apply({pi: 3.14159}, [10]))    // apply(obj,[])
  console.log(round.area.call({pi: 3.14159}, '10'))    // call(obj,'str')
  let newRound = round.area.bind({pi: 3.14159}, '10')
  console.log(newRound())   // bind 要再调用一下

 Object.freeze(obj) 冻结对象,不能修改属性值,不报错,修改无效    

Object.seal(obj)  冻结对象属性 ,不能删除属性,不报错,删除无效

MVVM: M 数据  V 视图  VM 监听数据改变更新视图,所以只需要关注数据逻辑,不需要操作DOM

VUE响应式原理:

vue采用数据劫持结合发布者-订阅者模式的方式,通过Object.definedProperty()劫持各个属性的setter,getter,在数据变动时,发布消息给订阅者,触发相应的监听回调

Observer.js 利用Object.definedProperty() 监听属性的getter, setter, 实现一个消息订阅器,通知订阅者Watcher,
Compile.js 解析模板指令,替换成数据,渲染视图,先把dom节点转换成文档碎片fragment,提高性能

watcher.js 属性变动,接收到消息通知时,调用自身的update()方法,触发Compile中绑定的回调,更新视图

    

watch: {
      obj: {
      handler (newValue, oldValue) {
        console.log('obj changed')
      },
      deep: true
    }
  }
给 data 添加新属性 this.$set(this.obj, 'b', 'obj.b')
数组的delete
let arr = [1,2,3,4]
delete arr[1] // 下标不变 0,2 3
vue的 this.$delete // 下标重新变成 0,1,2

vue-router 默认 hash模式,单页应用,当url改变时,页面不会重新加载
还有history模式,利用h5的history.pushState来跳转,需要后台配置一个静态页面,当url匹配不到时时进行跳转
地址变更的监听, window.addEventListener('hashchange',()=>{})

vue-router作为一个插件,使用Vue.use()来注册;new Vue()时会执行vue-router注入的beforeCreate()钩子函数,执行 hashchange,会匹配到地址route, 赋值给vm._route, 被Vue的数据劫持拦截到,触发视图更新

vuex

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

// 只用 state 和 mutations 不用常量,不用getters(过滤state数据) 和 actions(异步提交 mutation)
export default new Vuex.Store({
state: {
money: 10
},
mutations: {
money (state, val) {
state.money = val
}
}
})
getState(){
console.log(this.$store.state['money']) // get
},
setState(){
this.$store.commit('money',30) // set
}
main.js 全局 setVuex getVuex
Vue.prototype.setVuex = function (key, val) {
return this.$store.commit(key, val)
}
Vue.prototype.getVuex=function (val) {
return this.$store.state[val]
}
fetch
es6新出,只有网络故障时或请求被阻止时,才会reject() 后端返回404 500,要自己处理 promise 之前 是 xmlHttpRequest

scoreCalcAPI.js
let develop = 'xx' // 开发
let release = 'xx'   // 测试
/*
 * 将用户在各应用的行为,发送给会管家,由会管家计算用户的分享,分销积分.
 * obj: 接口参数对象
 * obj={
      AppId: "xx",                           // 应用Id
      UserId: "xx",      // 用户Id
      MarkId: "xx",  // 触发表主键Id,如添加了一条分享邀约,此处填分享邀约的Id
      MarkDesc: "xx",                          // 触发内容,如添加了一条分享邀约,此处填分享邀约标题,若是评论,则填写评论的内容.
      ChannelCode: "xx",            // 渠道编号
      RuleType: xx,                                 // 数值
    }

 * */
function scoreCalcAPI (obj) {
  let URL, href = window.location.href
   if (href.indexOf('http://p')>0) {
    URL = production
  } else {
    URL = release
  }
  let xmlhttp = new XMLHttpRequest();
  xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
      // 请求成功
      console.log(xmlhttp.responseText);
    }
  }
  xmlhttp.open("post", URL+ 'api/commonapi/pushpoint', true);
  xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  xmlhttp.send("pointdata=" + JSON.stringify(obj));
}
View Code

Synthesis.js  canvas图片合成

export class SynthesisShare {
  constructor(w, h) {
    //初始化canvas
    let canvas = document.createElement("canvas")
    canvas.width = w
    canvas.height = h
    this.canvas = canvas
    this.ctx = canvas.getContext("2d")
  }

  /**
   * 合成图片元素
   * @param elements 一个包含了SynthesisElement类的数组
   * @returns {string} 合成后图片数据
   */
  synthesisImage(elements) {
    this.clear()
    if (Array.isArray(elements)) {
      for (let i = 0; i < elements.length; i++) {
        let e = elements[i]
        this.drawElement(e)
      }
    } else {
      this.drawElement(elements)
    }
    return this.canvas.toDataURL('image/png')
  }

  drawElement(e) {
    this.ctx.drawImage(e.image, e.x, e.y, e.w, e.h)
  }

  /**
   * 方便多次复用canvas,清理画面
   */
  clear() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }
}

/**
 * 合成元素类
 */
export class SynthesisElement {
  constructor() {
    this.url = ''
    this.x = 0
    this.y = 0
    this.w = 0
    this.h = 0
    this.image = null
  }

  /**
   * 初始化合成元素
   * @param url 图片地址
   * @param x  x坐标
   * @param y  y坐标
   * @param w  宽
   * @param h  高
   * @returns {Promise<void>}
   */
  async init(url, x, y, w, h) {
    this.url = url
    this.x = x
    this.y = y
    this.w = w
    this.h = h
    this.image = await this.loadImage(url)
  }

  /**
   * 加载元素图片
   * @param url
   * @returns {Promise<any>}
   */
  loadImage(url) {
    // console.log(url);
    return new Promise((resolve, reject) => {
      let img = new Image();
      img.setAttribute('crossOrigin', '*');
      if (!url) {
        reject('err')
      }
      img.src = url
      img.onload = () => {
        resolve(img)
      }
    })
  }
}
View Code

 



posted @ 2018-12-17 14:10  gyz418  阅读(202)  评论(2编辑  收藏  举报