js相關(guān)學(xué)習(xí)

一妄讯、 原型和原型鏈

  • 所有的引用類型(數(shù)組孩锡、函數(shù)、對(duì)象)可以自由擴(kuò)展屬性(除null以外)亥贸。
  • 引用類型有一個(gè)_ _ proto_ _屬性(也叫隱式原型躬窜,它是一個(gè)普通的對(duì)象)。
  • 函數(shù)有一個(gè)prototype屬性(這也叫顯式原型炕置,它也是一個(gè)普通的對(duì)象)荣挨。
  • 引用類型的_ _ proto_ _指向它構(gòu)造函數(shù)的prototype
  • 當(dāng)試圖得到一個(gè)對(duì)象的屬性時(shí)朴摊,如果這個(gè)對(duì)象本身不存在這個(gè)屬性默垄,那么就會(huì)去它的_ _ proto_ _屬性(也就是它的構(gòu)造函數(shù)的’prototype’屬性)中去尋找。
function Person() {
}
var person = new Person();
console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
// 順便學(xué)習(xí)一個(gè)ES5的方法,可以獲得對(duì)象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
  • 原型鏈:利用原型讓一個(gè)引用類型繼承另一個(gè)引用類型的屬性和方法仍劈。然后層層遞進(jìn)厕倍,就構(gòu)成了實(shí)例與原型的鏈條。


    image.png
  • new操作符具體干了什么呢贩疙?
    1讹弯、創(chuàng)建一個(gè)空對(duì)象况既,并且 this 變量引用該對(duì)象,同時(shí)還繼承了該函數(shù)的原型组民。
    2棒仍、屬性和方法被加入到 this 引用的對(duì)象中。
    3臭胜、新創(chuàng)建的對(duì)象由 this 所引用莫其,并且最后隱式的返回 this 。

閉包

閉包是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)
1.優(yōu)點(diǎn):

  • 變量長(zhǎng)期駐扎在內(nèi)存中;
  • 避免全局變量的污染;
  • 私有成員的存在 溶弟;
    2. 特性
  • 函數(shù)套函數(shù);
  • 內(nèi)部函數(shù)可以直接使用外部函數(shù)的局部變量或參數(shù)憨颠;
  • 變量或參數(shù)不會(huì)被垃圾回收機(jī)制回收 GC;
    3.缺點(diǎn)
    常駐內(nèi)存 會(huì)增大內(nèi)存的使用量 使用不當(dāng)會(huì)造成內(nèi)存泄露积锅,詳解:
  • 內(nèi)存泄漏:每個(gè)瀏覽器會(huì)有自己的一套回收機(jī)制爽彤,當(dāng)分配出去的內(nèi)存不使用的時(shí)候便會(huì)回收;內(nèi)存泄露的根本原因就是你的代碼中分配了一些‘頑固的’內(nèi)存缚陷,瀏覽器無法進(jìn)行回收适篙,如果這些’頑固的’內(nèi)存還在一直不停地分配就會(huì)導(dǎo)致后面所用內(nèi)存不足,造成泄露箫爷。
  • 由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中嚷节,內(nèi)存消耗很大,所以不能濫用閉包虎锚,否則會(huì)造成網(wǎng)頁的性能問題丹喻,導(dǎo)致內(nèi)存泄露。解決方法是翁都,在退出函數(shù)之前,將不使用的局部變量全部刪除谅猾。

// setTimeout保存循環(huán)中的值

for(var i=0; i< 10; i++) {
    setTimeout((function(i) {
        console.log(i);
    })(i));
}
i = null;

堆和棧

堆和棧在不同的場(chǎng)景下柄慰,有不同的含義:
(1)程序內(nèi)存布局場(chǎng)景下,堆與棧表示兩種內(nèi)存管理方式税娜;
(2)數(shù)據(jù)結(jié)構(gòu)場(chǎng)景下坐搔,堆與棧表示兩種常用的數(shù)據(jù)結(jié)構(gòu)。

  1. 這里說的是內(nèi)存中的堆和棧
  • 變量都存放在內(nèi)存中

  • 內(nèi)存給變量開辟了兩塊區(qū)域,分別為棧區(qū)域和堆區(qū)域

  • 棧的特點(diǎn),開口向上,速度快,容量小

  • 堆的特點(diǎn),速度稍慢,容量比較大

  • 棧(stack)
    棧區(qū)存放基本類型和引用類型的指針


    image.png
  • 堆(heap)
    堆區(qū)存放引用類型敬矩,比如:Array概行,Object對(duì)象


    image.png

    補(bǔ)充:

  • 基本類型: undefined,boolean弧岳,number凳忙,string业踏,null.

  • 引用類型:object、Array涧卵、RegExp勤家、Date、Function柳恐、特殊的基本包裝類型(String伐脖、Number、Boolean)以及單體內(nèi)置對(duì)象(Global乐设、Math)讼庇。

數(shù)據(jù)查詢速度比較,stack遠(yuǎn)遠(yuǎn)大于heap近尚。
在實(shí)際開發(fā)過程中蠕啄,偶爾遇到棧溢出的情況,stack overflow錯(cuò)誤肿男,因?yàn)閟tack創(chuàng)建時(shí)候介汹,大小是確定的,超過額度大小就會(huì)發(fā)生棧溢出【當(dāng)js出現(xiàn)死循環(huán)或者錯(cuò)誤的遞歸時(shí)候】舶沛。heap大小是不確定的嘹承,需要可以一直累加。
js是單線程的如庭,那么怎么利用多核的CPU呢叹卷?H5的Web Worker標(biāo)準(zhǔn),允許js腳本創(chuàng)建多個(gè)線程坪它,但是子線程受主線程的控制骤竹,且不能操作DOM。
stack是線程獨(dú)占的往毡,heap是線程共有的蒙揣。

  • 基本包裝類型
    String Number Boolean這三個(gè)基本類型有其對(duì)應(yīng)的包裝對(duì)象,包裝對(duì)象有其對(duì)應(yīng)的屬性和方法开瞭,調(diào)用方法的過程是在后臺(tái)發(fā)生的
var str = 'hello'; //string 基本類型
var s2 = str.charAt(0); //在執(zhí)行到這一句的時(shí)候 后臺(tái)會(huì)自動(dòng)完成以下動(dòng)作 :
( 
 var _str = new String('hello'); // 1 找到對(duì)應(yīng)的包裝對(duì)象類型懒震,然后通過包裝對(duì)象創(chuàng)建出一個(gè)和基本類型值相同的對(duì)象
 var s2 = _str.chaAt(0); // 2 然后這個(gè)對(duì)象就可以調(diào)用包裝對(duì)象下的方法,并且返回結(jié)給s2.
 _str = null;  //    3 之后這個(gè)臨時(shí)創(chuàng)建的對(duì)象就被銷毀了嗤详, str =null; 
 ) 
alert(s2);//h 
alert(str);//hello

注意這一瞬間个扰,我們并沒有改變?cè)址畇tr的值,只是新建了一個(gè)_str對(duì)象得出結(jié)果葱色,賦值給s2
引用類型創(chuàng)建的對(duì)象在執(zhí)行期間一直存在递宅,包裝類型創(chuàng)建的對(duì)象只存在了一瞬間

  1. 淺拷貝和深拷貝
  • 淺拷貝,拷貝了對(duì)象的引用,原對(duì)象變化時(shí)办龄,拷貝對(duì)象變化
  • 深拷貝烘绽,拷貝了對(duì)象的值,原對(duì)象變化時(shí)土榴,拷貝對(duì)象不變
    深拷貝的方法
  • obj2 = Object.assign({}, obj1)
    創(chuàng)建了一個(gè)空對(duì)象诀姚,把obj1屬性復(fù)制過去,obj1改變不會(huì)影響obj2
  • obj2 = JSON.parse(JSON.stringify(obj1))
    JSON.stringify把對(duì)象轉(zhuǎn)成字符串玷禽,JSON.parser把字符串轉(zhuǎn)成新對(duì)象
  • 遞歸拷貝

瀏覽器渲染原理

1.瀏覽器渲染過程

  • HTML文檔解析成DOM樹 赫段。
  • 處理CSS標(biāo)記,構(gòu)成層疊樣式表模型CSSOM(CSS Object Model)
  • 將DOM和CSSOM合并為渲染樹(rendering tree)矢赁。
    在這一過程中糯笙,不是簡(jiǎn)單的將兩者合并就行了。渲染樹只會(huì)包括需要顯示的節(jié)點(diǎn)和這些節(jié)點(diǎn)的樣式信息撩银,如果某個(gè)節(jié)點(diǎn)是 display: none 的给涕,那么就不會(huì)在渲染樹中顯示。
  • 當(dāng)瀏覽器生成渲染樹之后额获,就會(huì)根據(jù)渲染樹來進(jìn)行布局够庙。這一個(gè)階段瀏覽器要做的事情就是要弄清楚每個(gè)節(jié)點(diǎn)在頁面中的確切位置和大小。通常這一個(gè)行為也叫做自動(dòng)重排抄邀。
    布局流程的輸出是一個(gè)盒模型耘眨,它會(huì)精確的捕獲每個(gè)元素在視口內(nèi)的確切位置和尺寸,所有相對(duì)測(cè)量值都將轉(zhuǎn)換成屏幕上的絕對(duì)像素境肾。


    image.png

2.渲染阻塞

構(gòu)建DOM樹和CSSOM樹時(shí)剔难,遇到JS,整個(gè)解析進(jìn)程必須等待JS的執(zhí)行完成才能夠繼續(xù)奥喻,這就是所謂的JS阻塞頁面偶宫。
每次去執(zhí)行JavaScript腳本都會(huì)嚴(yán)重地阻塞DOM樹的構(gòu)建,如果JavaScript腳本還操作了CSSOM环鲤,而正好這個(gè)CSSOM還沒有下載和構(gòu)建纯趋,瀏覽器甚至?xí)舆t腳本執(zhí)行和構(gòu)建DOM,直至完成其CSSOM的下載和構(gòu)建冷离。所以结闸,script標(biāo)簽的位置很重要。

由于CSSOM負(fù)責(zé)存儲(chǔ)渲染信息酒朵,瀏覽器就必須保證在合成渲染樹之前,CSSOM和DOM的解析完全結(jié)束扎附,瀏覽器才會(huì)進(jìn)入下一步的渲染蔫耽,這就是CSS阻塞渲染。
CSS阻塞渲染意味著,在CSSOM完備前匙铡,頁面將一直處理白屏狀態(tài)图甜,這就是為什么樣式放在head中,僅僅是為了更快的解析CSS鳖眼,保證更快的首次渲染黑毅。

需要注意的是,即便你沒有給頁面任何的樣式聲明钦讳,CSSOM依然會(huì)生成矿瘦,默認(rèn)生成的CSSOM自帶瀏覽器默認(rèn)樣式。

3. 回流(重排)和重繪(reflow和repaint)

HTML默認(rèn)是流式布局的愿卒,但CSS和JS會(huì)打破這種布局缚去,改變DOM的外觀樣式以及大小和位置。因此我們就需要知道兩個(gè)概念:replaint和reflow琼开。

3.1 reflow(回流/重排)

當(dāng)瀏覽器發(fā)現(xiàn)布局發(fā)生了變化易结,這個(gè)時(shí)候就需要倒回去重新渲染,大家稱這個(gè)回退的過程叫reflow柜候。
reflow會(huì)從html這個(gè)root frame開始遞歸往下搞动,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置,以確認(rèn)是渲染樹的哪一部分發(fā)生變化還是整個(gè)渲染樹渣刷。reflow幾乎是無法避免的鹦肿,因?yàn)橹灰脩暨M(jìn)行交互操作,就勢(shì)必會(huì)發(fā)生頁面的一部分的重新渲染飞主,且通常我們也無法預(yù)估瀏覽器到底會(huì)reflow哪一部分的代碼狮惜,因?yàn)樗麄儠?huì)相互影響。

3.2 repaint(重繪)

repaint則是當(dāng)我們改變某個(gè)元素的背景色碌识、文字顏色碾篡、邊框顏色等等不影響它周圍或內(nèi)部布局的屬性時(shí),屏幕的一部分要重畫筏餐,但是元素的幾何尺寸和位置沒有發(fā)生改變开泽。

注意,display:none會(huì)觸發(fā)reflow魁瞪,visibility: hidden只會(huì)觸發(fā)repaint
visibiliy是隱藏元素穆律,但元素仍然占據(jù)著布局空間,它會(huì)被渲染成一個(gè)空框导俘。所以visibility:hidden只會(huì)觸發(fā)repaint峦耘,因?yàn)闆]有發(fā)生位置變化。

另外旅薄,修改了元素的樣式辅髓,瀏覽器并不會(huì)立刻reflow或repaint一次,而是會(huì)把這樣的操作積攢一批,然后做一次reflow洛口,這又叫異步reflow或增量異步reflow矫付。
但是在有些情況下,比如resize窗口第焰,改變了頁面默認(rèn)的字體等买优。對(duì)于這些操作,瀏覽器會(huì)馬上進(jìn)行reflow挺举。

3.3 引起reflow

現(xiàn)代瀏覽器會(huì)對(duì)回流做優(yōu)化杀赢,它會(huì)等到足夠數(shù)量的變化發(fā)生,再做一次批處理回流豹悬。

  • 頁面第一次渲染(初始化)
  • DOM樹變化(如:增刪節(jié)點(diǎn))
  • Render樹變化(如:padding改變)
  • 瀏覽器窗口resize
  • 獲取元素的某些屬性
    瀏覽器為了獲得正確的值也會(huì)提前觸發(fā)回流葵陵,這樣就使得瀏覽器的優(yōu)化失效了,這些屬性包括offsetLeft瞻佛、offsetTop脱篙、offsetWidth、offsetHeight伤柄、 scrollTop/Left/Width/Height绊困、clientTop/Left/Width/Height、調(diào)用了getComputedStyle()适刀。

3.4 引起repaint

reflow回流必定引起repaint重繪秤朗,重繪可以單獨(dú)觸發(fā)。
背景色笔喉、顏色取视、字體改變(注意:字體大小發(fā)生變化時(shí),會(huì)觸發(fā)回流)

3.5 減少reflow常挚、repaint觸發(fā)次數(shù)

  • 用transform做形變和位移可以減少reflow
  • 避免逐個(gè)修改節(jié)點(diǎn)樣式作谭,盡量一次性修改
  • 使用DocumentFragment將需要多次修改的DOM元素緩存,最后一次性append到真實(shí)DOM中渲染
  • 可以將需要多次修改的DOM元素設(shè)置display:none奄毡,操作完再顯示折欠。(因?yàn)殡[藏元素不在render樹內(nèi),因此修改隱藏元素不會(huì)觸發(fā)回流重繪)
  • 避免多次讀取某些屬性
  • 通過絕對(duì)位移將復(fù)雜的節(jié)點(diǎn)元素脫離文檔流吼过,形成新的Render Layer锐秦,降低回流成本

4. 幾條關(guān)于優(yōu)化渲染效率的建議

  • 合法地去書寫HTML和CSS ,且不要忘了文檔編碼類型盗忱。
  • 樣式文件應(yīng)當(dāng)在head標(biāo)簽中酱床,而腳本文件在body結(jié)束前,這樣可以防止阻塞的方式趟佃。
  • 簡(jiǎn)化并優(yōu)化CSS選擇器斤葱,盡量將嵌套層減少到最小慷垮。
  • DOM 的多個(gè)讀操作(或多個(gè)寫操作),應(yīng)該放在一起揍堕。不要兩個(gè)讀操作之間,加入一個(gè)寫操作汤纸。
  • 如果某個(gè)樣式是通過重排得到的衩茸,那么最好緩存結(jié)果。避免下一次用到的時(shí)候贮泞,瀏覽器又要重排
  • 不要一條條地改變樣式楞慈,而要通過改變class,或者csstext屬性啃擦,一次性地改變樣式囊蓝。
  • 盡量用transform來做形變和位移
  • 盡量使用離線DOM,而不是真實(shí)的網(wǎng)面DOM令蛉,來改變?cè)貥邮骄鬯1热纾僮鱀ocument Fragment對(duì)象珠叔,完成后再把這個(gè)對(duì)象加入DOM蝎宇。再比如,使用cloneNode()方法祷安,在克隆的節(jié)點(diǎn)上進(jìn)行操作姥芥,然后再用克隆的節(jié)點(diǎn)替換原始節(jié)點(diǎn)。
  • 先將元素設(shè)為display: none(需要1次重排和重繪)汇鞭,然后對(duì)這個(gè)節(jié)點(diǎn)進(jìn)行100次操作凉唐,最后再恢復(fù)顯示(需要1次重排和重繪)。這樣一來霍骄,你就用兩次重新渲染台囱,取代了可能高達(dá)100次的重新渲染。
  • position屬性為absolute或fixed的元素腕巡,重排的開銷會(huì)比較小玄坦,因?yàn)椴挥每紤]它對(duì)其他元素的影響
  • 只在必要的時(shí)候,才將元素的display屬性為可見绘沉,因?yàn)椴豢梢姷脑夭挥绊懼嘏藕椭乩L煎楣。另外,visibility : hidden的元素只對(duì)重繪有影響车伞,不影響重排择懂。
  • 使用window.requestAnimationFrame()、window.requestIdleCallback()這兩個(gè)方法調(diào)節(jié)重新渲染另玖。

http狀態(tài)碼

分類 分類描述
1** 信息困曙,服務(wù)器收到請(qǐng)求表伦,需要請(qǐng)求者繼續(xù)執(zhí)行操作
2** 成功,操作被成功接收并處理
3** 重定向慷丽,需要進(jìn)一步的操作以完成請(qǐng)求
4** 客戶端錯(cuò)誤蹦哼,請(qǐng)求包含語法錯(cuò)誤或無法完成請(qǐng)求
5** 服務(wù)器錯(cuò)誤,服務(wù)器在處理請(qǐng)求的過程中發(fā)生了錯(cuò)誤
狀態(tài)碼 狀態(tài)碼英文名稱 中文描述
200 OK 請(qǐng)求成功要糊。
301 Moved Permanently 永久移動(dòng)纲熏。資源(網(wǎng)頁等)被永久轉(zhuǎn)移到其它UR
302 Found 臨時(shí)移動(dòng)。與301類似锄俄。但資源只是臨時(shí)被移動(dòng)局劲。客戶端應(yīng)繼續(xù)使用原有URI
303 See Other 查看其它地址奶赠。與301類似鱼填。使用GET和POST請(qǐng)求查看
404 Not Found 請(qǐng)求的資源(網(wǎng)頁等)不存在
500 Internal Server Error 服務(wù)器內(nèi)部錯(cuò)誤,無法完成請(qǐng)求

使用301跳轉(zhuǎn)的場(chǎng)景
1)域名到期不想續(xù)費(fèi)(或者發(fā)現(xiàn)了更適合網(wǎng)站的域名)毅戈,想換個(gè)域名苹丸。
2)在搜索引擎的搜索結(jié)果中出現(xiàn)了不帶www的域名,而帶www的域名卻沒有收錄竹祷,這個(gè)時(shí)候可以用301重定向來告訴搜索引擎我們目標(biāo)的域名是哪一個(gè)谈跛。
3)空間服務(wù)器不穩(wěn)定,換空間的時(shí)候塑陵。

ajax

Ajax(Asynchronous JavaScript And XML)感憾,異步 JavaScript 和 XML,用于異步請(qǐng)求數(shù)據(jù)令花,在不刷新網(wǎng)頁的情況下更新頁面數(shù)據(jù)阻桅,提升用戶體驗(yàn)


image.png

3.優(yōu)缺點(diǎn)
優(yōu)點(diǎn):

  • 不刷新頁面的情況下更新數(shù)據(jù)
  • 使用異步的方式與服務(wù)器通信,不打斷用戶的操作
  • 可將一些后端的工作移到前端兼都,減少服務(wù)器與帶寬的負(fù)擔(dān)
  • Ajax使得界面與應(yīng)用分離嫂沉,也就是數(shù)據(jù)與呈現(xiàn)分離
    缺點(diǎn)
  • AJAX技術(shù)給用戶帶來很好的用戶體驗(yàn)但是會(huì)暴露比以前更多的數(shù)據(jù)和服務(wù)器邏輯
  • 對(duì)搜索引擎支持較弱
    4.實(shí)現(xiàn)
    核心XMLHttpRequest (簡(jiǎn)稱XHR),可以不刷新界面獲取更新數(shù)據(jù)扮碧,老版本的IE里使用ActiveXObject
    readyState存有 XMLHttpRequest的狀態(tài)趟章。從 0 到 4 發(fā)生變化。
    0: 請(qǐng)求未初始化
    1: 服務(wù)器連接已建立
    2: 請(qǐng)求已接收
    3: 請(qǐng)求處理中
    4: 請(qǐng)求已完成慎王,且響應(yīng)已就緒
    status
    200: "OK"
    404: 未找到頁面
    當(dāng) readyState 等于 4 且狀態(tài)為 200 時(shí)蚓土,表示響應(yīng)已就緒:
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>ajax</title>
    </head>
    <body>
        <div id="myDiv"><h2>Let Ajax change this text</h2></div>
        <button onclick="loadXMLDoc()">通過Ajax改變內(nèi)容</button>
    <script>
        function loadXMLDoc() {
            var xmlhttp;
            if(window.XMLHttpRequest) {
                xmlhttp = new XMLHttpRequest();
            } else {
                xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
            }
                      // 每當(dāng) readyState 屬性改變時(shí),就會(huì)調(diào)用該函數(shù)
            xmlhttp.onreadstatechange = function() {  
                if(xmlhttp.readystate == 4 && xmlhttp.status == 200) {
                    document.getElementById('myDiv').innerHTML = xmlhttp.responseText;
                }
            }
            xmlhttp.open('GET', '/ajax/test1.txt', true);
            xmlhttp.send();  // 將請(qǐng)求發(fā)送到服務(wù)器
        }
    </script>
    </body>
</html>

5.axios
Axios 是一個(gè)基于 promise 的 HTTP 庫赖淤,可以用在瀏覽器和 node.js 中

  • 從瀏覽器中創(chuàng)建 XMLHttpRequests
  • 從 node.js 創(chuàng)建 http 請(qǐng)求
  • 支持 PromiseAPI
  • 攔截請(qǐng)求和響應(yīng)
  • 轉(zhuǎn)換請(qǐng)求數(shù)據(jù)和響應(yīng)數(shù)據(jù)
  • 取消請(qǐng)求
  • 自動(dòng)轉(zhuǎn)換 JSON 數(shù)據(jù)
  • 客戶端支持防御 XSRF
    get參數(shù):{params:{}}, post參數(shù):{}
axios.get('/user', {
    params: {
      ID: 12345
    }
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });
axios.post('/user', {
    firstName: 'Fred',
    lastName: 'Flintstone'
  })
  .then(function (response) {
    console.log(response);
  })
  .catch(function (error) {
    console.log(error);
  });

瀏覽器數(shù)據(jù)存儲(chǔ)

存儲(chǔ)的方式有:
cookie蜀漆,localstorage,sessionstorage


111.png

cookie的弊端:
1.每次請(qǐng)求都會(huì)攜帶cookie里面的信息咱旱,增加流量的消耗
2.明文存儲(chǔ)不安全
3.用戶登錄之后确丢,關(guān)閉頁面绷耍,重新打開之后為什么還能獲取之前的用戶信息?
用戶登錄成功之后后臺(tái)會(huì)隨機(jī)生成一個(gè)用戶登錄信息(sessionId),并將登錄信息存放在cookie中鲜侥,下次訪問頁面時(shí)褂始,服務(wù)端會(huì)先去cookie中獲取sessionId,并判斷其真實(shí)有效性(可以用來處理單點(diǎn)登錄)

跨域

1.跨域出現(xiàn)的原因:瀏覽器的同源策略(同源策略是瀏覽器的安全策略)

  • 同源策略是瀏覽器的一個(gè)安全功能描函,不同源的客戶端腳本在沒有明確授權(quán)的情況下病袄,不能讀寫對(duì)方資源。
  • 是用于隔離潛在惡意文件的重要安全機(jī)制赘阀。
  • 同源(協(xié)議、域名脑奠、端口號(hào)相同)
當(dāng)前頁面url 被請(qǐng)求頁面url 是否跨域 原因
http://www.test.com/ http://www.test.com/index.html 同源(協(xié)議基公、域名、端口號(hào)相同)
http://www.test.com/ https://www.test.com/index.html 跨域 協(xié)議不同(http/https)
http://www.test.com/ http://www.baidu.com/ 跨域 主域名不同(test/baidu)
http://www.test.com/ http://blog.test.com/ 跨域 子域名不同(www/blog)
http://www.test.com:8080/ http://www.test.com:7001/ 跨域 端口號(hào)不同(8080/7001)

2.非同源限制

  • 無法讀取非同源網(wǎng)頁的 Cookie宋欺、LocalStorage 和 IndexedDB
  • 無法接觸非同源網(wǎng)頁的 DOM
  • 無法向非同源地址發(fā)送 AJAX 請(qǐng)求

3.跨域解決方法

(1) 設(shè)置document.domain解決無法讀取非同源網(wǎng)頁的 Cookie問題
因?yàn)闉g覽器是通過document.domain屬性來檢查兩個(gè)頁面是否同源轰豆,因此只要通過設(shè)置相同的document.domain,兩個(gè)頁面就可以共享Cookie(此方案僅限主域相同齿诞,子域不同的跨域應(yīng)用場(chǎng)景酸休。)

// 兩個(gè)頁面都設(shè)置
document.domain = 'test.com';

(2) 跨文檔通信 API:window.postMessage()
調(diào)用postMessage方法實(shí)現(xiàn)父窗口http://test1.com向子窗口http://test2.com發(fā)消息(子窗口同樣可以通過該方法發(fā)送消息給父窗口)

它可用于解決以下方面的問題:

  • 頁面和其打開的新窗口的數(shù)據(jù)傳遞
  • 多窗口之間消息傳遞
  • 頁面與嵌套的iframe消息傳遞
  • 上面三個(gè)場(chǎng)景的跨域數(shù)據(jù)傳遞

// 父窗口打開一個(gè)子窗口
var openWindow = window.open('http://test2.com', 'title');
 
// 父窗口向子窗口發(fā)消息(第一個(gè)參數(shù)代表發(fā)送的內(nèi)容,第二個(gè)參數(shù)代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test2.com');

調(diào)用message事件祷杈,監(jiān)聽對(duì)方發(fā)送的消息

// 監(jiān)聽 message 消息
window.addEventListener('message', function (e) {
  console.log(e.source); // e.source 發(fā)送消息的窗口
  console.log(e.origin); // e.origin 消息發(fā)向的網(wǎng)址
  console.log(e.data);   // e.data   發(fā)送的消息
},false);

(3) JSONP
JSONP 是服務(wù)器與客戶端跨源通信的常用方法斑司。最大特點(diǎn)就是簡(jiǎn)單適用,兼容性好(兼容低版本IE)但汞,缺點(diǎn)是只支持get請(qǐng)求宿刮,不支持post請(qǐng)求。
核心思想:網(wǎng)頁通過添加一個(gè)<script>元素私蕾,向服務(wù)器請(qǐng)求 JSON 數(shù)據(jù)僵缺,服務(wù)器收到請(qǐng)求后,將數(shù)據(jù)放在一個(gè)指定名字的回調(diào)函數(shù)的參數(shù)位置傳回來踩叭。

  • 原生實(shí)現(xiàn):
<script src="http://test.com/data.php?callback=dosomething"></script>
// 向服務(wù)器test.com發(fā)出請(qǐng)求磕潮,該請(qǐng)求的查詢字符串有一個(gè)callback參數(shù),用來指定回調(diào)函數(shù)的名字
 
// 處理服務(wù)器返回回調(diào)函數(shù)的數(shù)據(jù)
<script type="text/javascript">
    function dosomething(res){
        // 處理獲得的數(shù)據(jù)
        console.log(res.data)
    }
</script>
  • jQuery ajax
$.ajax({
    url: 'http://www.test.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 請(qǐng)求方式為jsonp
    jsonpCallback: "handleCallback",    // 自定義回調(diào)函數(shù)名
    data: {}
});
  • Vue.js
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

(4) 配置webpack代理解決跨域

proxyTable: {
        '/api': {
            target: 'http://beta-pvg.goms.com.cn',
            changeOrigin: true, //是否跨域
            pathRewrite: {
                '^/api': ''
            }
        }
},

4.CORS
CORS 是跨域資源分享(Cross-Origin Resource Sharing)的縮寫容贝。它是 W3C 標(biāo)準(zhǔn)自脯,屬于跨源 AJAX 請(qǐng)求的根本解決方法。
(1) 普通跨域請(qǐng)求:只需服務(wù)器端設(shè)置Access-Control-Allow-Origin
(2) 帶cookie跨域請(qǐng)求:前后端都需要進(jìn)行設(shè)置
【前端設(shè)置】根據(jù)xhr.withCredentials字段判斷是否帶有cookie

web安全問題

1.SQL注入(SQL Injection)

定義
由于程序中對(duì)用戶輸入檢查不嚴(yán)格嗤疯,用戶可以提交一段數(shù)據(jù)庫查詢代碼冤今,根據(jù)程序返回的結(jié)果,獲得某些他想得知的數(shù)據(jù)茂缚,這就是所謂的SQL Injection戏罢,即SQL注入屋谭。
原因分析
其本質(zhì)是對(duì)于輸入檢查不充分,導(dǎo)致SQL語句將用戶提交的非法數(shù)據(jù)當(dāng)作語句的一部分來執(zhí)行龟糕。
風(fēng)險(xiǎn)
SQL盲注:如果系統(tǒng)屏蔽了詳細(xì)的錯(cuò)誤信息桐磁,那么對(duì)攻擊者而言就是盲注入,可能會(huì)查看讲岁、修改或刪除數(shù)據(jù)庫條目和表
使用SQL注入的認(rèn)證旁路:可能會(huì)繞開 Web 應(yīng)用程序的認(rèn)證機(jī)制
例子

image.png

預(yù)防措施

  • 不要使用動(dòng)態(tài)SQL
    避免將用戶提供的輸入直接放入SQL語句中我擂;最好使用準(zhǔn)備好的語句和參數(shù)化查詢,這樣更安全缓艳。
  • 不要將敏感數(shù)據(jù)保留在純文本中
    加密存儲(chǔ)在數(shù)據(jù)庫中的私有/機(jī)密數(shù)據(jù)校摩;這樣可以提供了另一級(jí)保護(hù),以防攻擊者成功地排出敏感數(shù)據(jù)阶淘。
  • 限制數(shù)據(jù)庫權(quán)限和特權(quán)
    將數(shù)據(jù)庫用戶的功能設(shè)置為最低要求衙吩;這將限制攻擊者在設(shè)法獲取訪問權(quán)限時(shí)可以執(zhí)行的操作。
  • 避免直接向用戶顯示數(shù)據(jù)庫錯(cuò)誤
    攻擊者可以使用這些錯(cuò)誤消息來獲取有關(guān)數(shù)據(jù)庫的信息溪窒。
  • 對(duì)訪問數(shù)據(jù)庫的Web應(yīng)用程序使用Web應(yīng)用程序防火墻(WAF)
    這為面向Web的應(yīng)用程序提供了保護(hù)坤塞,它可以幫助識(shí)別SQL注入嘗試;根據(jù)設(shè)置澈蚌,它還可以幫助防止SQL注入嘗試到達(dá)應(yīng)用程序(以及數(shù)據(jù)庫)摹芙。
  • 定期測(cè)試與數(shù)據(jù)庫交互的Web應(yīng)用程序
    這樣做可以幫助捕獲可能允許SQL注入的新錯(cuò)誤或回歸。
  • 將數(shù)據(jù)庫更新為最新的可用修補(bǔ)程序
    這可以防止攻擊者利用舊版本中存在的已知弱點(diǎn)/錯(cuò)誤宛瞄。

2.跨站腳本攻擊(XSS)

定義
XSS攻擊是Web攻擊中最常見的攻擊方法之一浮禾,它是通過對(duì)網(wǎng)頁注入可執(zhí)行代碼且成功地被瀏覽器 執(zhí)行,達(dá)到攻擊的目的
形成了一次有效XSS攻擊坛悉,一旦攻擊成功伐厌,它可以獲取用戶的聯(lián)系人列表,然后向聯(lián)系人發(fā)送虛假詐騙信息裸影,可以刪除用戶的日志等等挣轨,有時(shí)候還和其他攻擊方式同時(shí)實(shí) 施比如SQL注入攻擊服務(wù)器和數(shù)據(jù)庫、Click劫持轩猩、相對(duì)鏈接劫持等實(shí)施釣魚卷扮,它帶來的危害是巨 大的,是web安全的頭號(hào)大敵均践。
分類
XSS反射型攻擊晤锹,惡意代碼并沒有保存在目標(biāo)網(wǎng)站,通過引誘用戶點(diǎn)擊一個(gè)鏈接到目標(biāo)網(wǎng)站的惡意鏈接來實(shí)施攻擊的彤委。
XSS存儲(chǔ)型攻擊鞭铆,惡意代碼被保存到目標(biāo)網(wǎng)站的服務(wù)器中,這種攻擊具有較強(qiáng)的穩(wěn)定性和持久性焦影,比較常見場(chǎng)景是在博客车遂,論壇等社交網(wǎng)站上封断,但OA系統(tǒng),和CRM系統(tǒng)上也能看到它身影舶担,比如:某CRM系統(tǒng)的客戶投訴功能上存在XSS存儲(chǔ)型漏洞坡疼,黑客提交了惡意攻擊代碼,當(dāng)系統(tǒng)管理員查看投訴信息時(shí)惡意代碼執(zhí)行衣陶,竊取了客戶的資料柄瑰,然而管理員毫不知情,這就是典型的XSS存儲(chǔ)型攻擊剪况。
例子:

image.png

對(duì)用戶提交的所有內(nèi)容進(jìn)行過濾教沾,對(duì)url中的參數(shù)進(jìn)行過濾,過濾掉會(huì)導(dǎo)致腳本執(zhí)行的相關(guān)內(nèi)容译断;
對(duì)動(dòng)態(tài)輸出到頁面的內(nèi)容進(jìn)行html編碼详囤,使腳本無法在瀏覽器中執(zhí)行。

對(duì)輸入的內(nèi)容進(jìn)行過濾镐作,可以分為黑名單過濾和白名單過濾。黑名單過濾雖然可以攔截大部分的XSS攻擊隆箩,但是還是存在被繞過的風(fēng)險(xiǎn)该贾。白名單過濾雖然可以基本杜絕XSS攻擊,但是真實(shí)環(huán)境中一般是不能進(jìn)行如此嚴(yán)格的白名單過濾的捌臊。

對(duì)輸出進(jìn)行html編碼杨蛋,就是通過函數(shù),將用戶的輸入的數(shù)據(jù)進(jìn)行html編碼理澎,使其不能作為腳本運(yùn)行逞力。

如下,是使用php中的htmlspecialchars函數(shù)對(duì)用戶輸入的name參數(shù)進(jìn)行html編碼糠爬,將其轉(zhuǎn)換為html實(shí)體

#使用htmlspecialchars函數(shù)對(duì)用戶輸入的name參數(shù)進(jìn)行html編碼寇荧,將其轉(zhuǎn)換為html實(shí)體
$name = htmlspecialchars( $_GET[ 'name' ] );

如下,圖一是沒有進(jìn)行html編碼的执隧,圖2是進(jìn)行了html編碼的揩抡。經(jīng)過html編碼后script標(biāo)簽被當(dāng)成了html實(shí)體。


image.png

image.png

我們還可以服務(wù)端設(shè)置會(huì)話Cookie的HTTP Only屬性镀琉,這樣峦嗤,客戶端的JS腳本就不能獲取Cookie信息了

3.跨站請(qǐng)求偽造(CSRF/XSRF )

在瀏覽器的同源策略的約束下,對(duì)于跨域資源交互進(jìn)行處理時(shí),【通常允許跨域資源嵌入(Cross-origin embedding)】
下面是常見跨域資源嵌入示例:

  • <script src="..."></script>標(biāo)簽嵌入跨域腳本。語法錯(cuò)誤信息只能在同源腳本中捕捉到豺裆。
  • <img>嵌入圖片逸尖。支持的圖片格式包括PNG,JPEG,GIF,BMP,SVG,...
  • <video> 和 <audio>嵌入多媒體資源知染。
    CSRF 攻擊的原理魔招,就是利用由于瀏覽器的同源策略對(duì)以上嵌入資源不做限制的行為進(jìn)行跨站請(qǐng)求偽造的舱污。

3.1 CSRF 攻擊原理

image.png
  • 用戶瀏覽位于目標(biāo)服務(wù)器 A 的網(wǎng)站胶逢。并通過登錄驗(yàn)證曹体。
  • 獲取到 cookie_session_id俗扇,保存到瀏覽器 cookie 中
  • 在未登出服務(wù)器 A ,并在 session_id 失效前用戶瀏覽位于 hacked server B 上的網(wǎng)站箕别。
  • server B 網(wǎng)站中的<img src = "http://www.altoromutual.com/bank/transfer.aspx?creditAccount=1001160141&transferAmount=1000">嵌入資源起了作用铜幽,迫使用戶訪問目標(biāo)服務(wù)器 A
  • 由于用戶未登出服務(wù)器 A 并且 sessionId 未失效,請(qǐng)求通過驗(yàn)證串稀,非法請(qǐng)求被執(zhí)行

3.2 如何防御 CSRF

  • referer 驗(yàn)證解決方案除抛。
    最簡(jiǎn)單的方法依賴于瀏覽器引用頁頭部。大多數(shù)瀏覽器會(huì)告訴 Web 服務(wù)器母截,哪個(gè)頁面發(fā)送了請(qǐng)求到忽。如:
POST /bank/transfer.aspx HTTP/1.1
Referer: http://evilsite.com/myevilblog
User-Agent: Mozilla/4....
Host: www.altoromutual.com
Content-Length: 42
Cookie: SessionId=x3q2v0qpjc0n1c55mf35fxid;

不少站點(diǎn)通過 referer 驗(yàn)證來防止盜鏈本站圖片資源。
不過由于 http 頭在某些版本的瀏覽器上存在可被篡改的可能性清寇,所以這個(gè)解決方案并不完善

  • Token 解決方案
    令牌解決方案向表單添加一個(gè)參數(shù)喘漏,讓表單在用戶注銷時(shí)或一個(gè)超時(shí)期限結(jié)束后過期
<form id="transferForm" action="https://www.altoromutual.com/bank/transfer.aspx" method="post">

Enter the credit account:
<input type="text" name="creditAccount" value="">
Enter the transfer amount:
<input type="text" name="transferAmount" value="">

<input type="hidden" name="xsrftoken" value="JKBS38633jjhg0987PPll">

<input type="submit" value="Submit">

</form>

或者將服務(wù)端動(dòng)態(tài)生成的 Token 加入到 自定義 http 請(qǐng)求頭參數(shù)中

POST /bank/transfer.aspx HTTP/1.1
Referer: https://www.altoromutual.com/bank
xsrftoken: JKBS38633jjhg0987PPll
User-Agent: Mozilla/4....
Host: www.altoromutual.com
Content-Length: 42
Cookie: SessionId=x3q2v0qpjc0n1c55mf35fxid;

creditAccount=1001160141&transferAmount=10

token 解決方案的問題在于前后端代碼的巨大變更。并且每一步都動(dòng)態(tài)生成 token 并且對(duì) token 進(jìn)行驗(yàn)證的話华烟,也會(huì)造成額外的資源開銷翩迈。可以嘗試在關(guān)鍵性操作的地方再加上 token 驗(yàn)證邏輯盔夜。但是负饲,token 驗(yàn)證所帶來的前后端代碼的變動(dòng)所帶來的消耗,則需要慎重考慮

  • userId 解決方案
    相對(duì)于 token 這樣的需要前后端邏輯作出改動(dòng)喂链,以及造成額外資源開銷的方式以外還有一種小巧的防范措施返十。就是用戶每次請(qǐng)求關(guān)鍵性數(shù)據(jù)時(shí),后端接口在設(shè)計(jì)時(shí)都需要用戶提交相關(guān)的 userId椭微。userId 可以存儲(chǔ)到瀏覽器的 localStorage 中洞坑,這樣便能進(jìn)一步提高接口安全性,防止跨站請(qǐng)求偽造蝇率。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末检诗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓢剿,更是在濱河造成了極大的恐慌逢慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件间狂,死亡現(xiàn)場(chǎng)離奇詭異攻泼,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門忙菠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來何鸡,“玉大人,你說我怎么就攤上這事牛欢÷饽校” “怎么了?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵傍睹,是天一觀的道長(zhǎng)隔盛。 經(jīng)常有香客問我,道長(zhǎng)拾稳,這世上最難降的妖魔是什么吮炕? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮访得,結(jié)果婚禮上龙亲,老公的妹妹穿的比我還像新娘。我一直安慰自己悍抑,他們只是感情好鳄炉,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著搜骡,像睡著了一般迎膜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浆兰,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音珊豹,去河邊找鬼簸呈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛店茶,可吹牛的內(nèi)容都是我干的蜕便。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼贩幻,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼轿腺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起丛楚,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤族壳,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后趣些,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體仿荆,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了拢操。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锦亦。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖令境,靈堂內(nèi)的尸體忽然破棺而出杠园,到底是詐尸還是另有隱情,我是刑警寧澤舔庶,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布抛蚁,位于F島的核電站,受9級(jí)特大地震影響栖茉,放射性物質(zhì)發(fā)生泄漏篮绿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一吕漂、第九天 我趴在偏房一處隱蔽的房頂上張望亲配。 院中可真熱鬧,春花似錦惶凝、人聲如沸吼虎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽思灰。三九已至,卻和暖如春混滔,著一層夾襖步出監(jiān)牢的瞬間洒疚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工坯屿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留油湖,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓领跛,卻偏偏與公主長(zhǎng)得像乏德,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子吠昭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容