20181217

web 安全   XSS  CSP CSRF 點擊劫持  OAuth cdnjavascript

/*
* 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

 es6html

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 >= 實際高 scrollHeightvue

  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

基本數據類型:棧內存java

函數柯里化node

在一個函數中,首先填充幾個參數,而後再返回一個新的函數的技術,稱爲函數的柯里化。一般可用於在不侵入函數的前提下,爲函數 預置通用參數,供屢次重複調用。mysql

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]nginx

重繪:元素改顏色等樣式不影響佈局,重繪元素,損耗不大es6

迴流:元素尺寸、結構變了,瀏覽器會從新渲染頁面,稱迴流。   迴流必重繪。   web

** 避免頻繁操做樣式,可彙總後統一 一次修改,把 DOM 離線後修改,好比:先把 DOM 給 display:none (有一次 Reflow),而後你修改 100 次,而後再把它顯示出來vue-router

頁面初次渲染
瀏覽器窗口大小改變
元素尺寸、位置、內容發生改變
元素字體大小變化
添加或者刪除可見的 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中綁定的回調,更新視圖

    


給 data 添加新屬性 watch: { obj: { handler (newValue, oldValue) { console.log('obj changed') }, deep: true } }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
本站公眾號
   歡迎關注本站公眾號,獲取更多信息