概述
本篇主要講述聲明前置、引用類型、函數(shù)作用域鏈、閉包、HTTP、Web安全和性能優(yōu)化
聲明前置
在進(jìn)入一個(gè)執(zhí)行環(huán)境后,先把 var
和 function
聲明的變量前置,再去順序執(zhí)行代碼,如果出現(xiàn)同名,則覆蓋。如果一個(gè)變量已經(jīng)有值(包括函數(shù))再 var
無效
引用類型
引用類型存儲的是變量的地址,賦值僅僅是地址的拷貝
var a = 1
function increase( num ){
return num += 1
}
increase( a )
console.log( a ) // 1
JavaScript 中引用類型即對象,對象存儲方式是,棧內(nèi)存中存儲地址,堆內(nèi)存中存儲數(shù)據(jù)
var obj = { a: 1 }
function increase( obj ){
obj.a += 1
}
increase( obj )
console.log( obj.a ) // 2
函數(shù)作用域鏈
函數(shù)在執(zhí)行過程中,先從自己內(nèi)部找變量,之后去創(chuàng)建當(dāng)前函數(shù)所在的作用域中尋找,依次向上
var a = 1
function fn1(){
function fn2(){
cnsole.log( a )
}
var a = 2
return fn2
}
var fn = fn1()
fn() // 2
var a = 1
function fn1(){
var a = 2
return fn2
}
function fn2(){
console.log( a )
}
var fn = fn1()
fn() // 1
閉包
一個(gè)函數(shù)引用了外部的變量,這個(gè)變量 + 函數(shù) === 閉包,外部作用域中的變量不能被釋放,可以通過函數(shù)來操作這個(gè)變量
function bindName( name ){
return function( action ){ // 此函數(shù) + name(argument[0])就是閉包
console.log( ` ${ name } is ${ action }ing ` )
}
}
var doing = bindName( 'xxx' )
doing( 'work' ) // xxx is working
doing( 'play' ) // xxx is playing
HTTP
HTTP(Hypertext Transfer Protocol)超文本傳輸協(xié)議,它是一種應(yīng)用層的協(xié)議,主要規(guī)定了電腦之間傳輸內(nèi)容的協(xié)議
- 應(yīng)用層協(xié)議:HTTP、DNS、SSH
- 傳輸層協(xié)議:TCP、UDP
- 網(wǎng)絡(luò)層協(xié)議:IP
- URI ==> 統(tǒng)一資源標(biāo)識符
- URL ==> 統(tǒng)一資源定位符
HTTP 報(bào)文(HTTP Message)
請求報(bào)文(Request Message)
// 請求行
method path HTTP/1.1
// 請求頭
key: value
Host: 域名
connection: 決定當(dāng)前的事務(wù)完成之后,是否會(huì)關(guān)閉網(wǎng)絡(luò)連接,如果該值是 keep-alive ,網(wǎng)絡(luò)連接就是持久的,不會(huì)關(guān)閉,使得對同一服務(wù)器的請求可以繼續(xù)在該連接上完成
Pragma: no-cache ==> 與 Cache-Control: no-cache 效果一致,強(qiáng)制要求緩存服務(wù)器在返回緩存的版本之前將請求提交到源頭服務(wù)器進(jìn)行驗(yàn)證
Cache-Control: no-cache ==> 同上
User-Agent: 用戶代理軟件的應(yīng)用類型、操作系統(tǒng)、軟件開發(fā)商以及版本號
Accept: 告知客戶端可以處理的內(nèi)容類型
Referer: 當(dāng)前請求頁面的來源頁面的地址,即表示當(dāng)前頁面是通過此來源頁面里的鏈接進(jìn)入的
Accept-Encoding: 將客戶端能夠理解的內(nèi)容編碼方式--通常是某種壓縮算法--進(jìn)行通知
Accept-Language: 客戶端聲明它可以理解的自然語言,以及優(yōu)先選擇的語言
If-None-Match: 條件式請求首部。對于 GET 和 HEAD 請求方法來說,當(dāng)且僅當(dāng)服務(wù)器上沒有任何資源的 ETag 屬性值與這個(gè)首部中列出的相匹配的時(shí)候,服務(wù)器端會(huì)才返回所請求的資源,響應(yīng)碼為 200
Cookie:
響應(yīng)報(bào)文(Response Message)
// 響應(yīng)行
HTTP/1.1 HTTP-Status-Code
// 響應(yīng)頭
Cache-Control: 被用于在 HTTP 請求和響應(yīng)中通過指定指令來實(shí)現(xiàn)緩存機(jī)制
Content-Encoding: 對特定媒體類型的數(shù)據(jù)進(jìn)行壓縮
Content-Type: 實(shí)際返回的內(nèi)容的內(nèi)容類型
Expires: 指定一個(gè)日期 | 時(shí)間,在這個(gè) 日期 | 時(shí)間之后,HTTP 響應(yīng)被認(rèn)為是過時(shí)的
Server: 處理請求的源頭服務(wù)器所用到的軟件相關(guān)信息
Set-Cookie: 服務(wù)器端向客戶端發(fā)送 Cookie
Strict-Transport-Security: 安全功能,告知瀏覽器只能通過 HTTPS 訪問當(dāng)前資源,禁止 HTTP 方式
Cookie + Session
使用 Cookie + Session 可以使得無狀態(tài)的 HTTP 請求可以記錄穩(wěn)定的狀態(tài)信息
- Cookie 是存儲在瀏覽器里的一小段數(shù)據(jù)
- Session 是一種讓服務(wù)器能夠識別某個(gè)用戶的機(jī)制,或者說特指服務(wù)器存儲的 Session 數(shù)據(jù)
很多網(wǎng)站的靜態(tài)資源使用 CDN 地址而非使用當(dāng)前網(wǎng)站域名
使用 CDN 加速。從 Cookie 角度上說,發(fā)送請求時(shí)都會(huì)帶上 Cookie,但是 Cookie 有跨域限制,即請求相同域名才會(huì)帶上 Cookie,CDN 與當(dāng)前域名不一致,故請求 CDN 資源時(shí)不會(huì)帶上 Cookie,使得請求加快,從而達(dá)到加速的目的
Session
- Session 在生產(chǎn)環(huán)境中保存在數(shù)據(jù)庫中
- Session 是基于 Cookie 實(shí)現(xiàn)的
Web 安全
- 傳輸數(shù)據(jù)安全
- 瀏覽器安全機(jī)制
- 常見攻擊: XSS 攻擊、CSRF 攻擊、點(diǎn)擊挾持
數(shù)據(jù)傳輸安全
只要使用 HTTP 協(xié)議,無論做任何安全措施都是徒勞的,只有 HTTPS 協(xié)議才能保證數(shù)據(jù)在傳輸過程中的安全
數(shù)據(jù)加密
- 對稱加密:加密和解密都是用同一密鑰
- 特點(diǎn): 速度快
- 常見算法:AES
- 非對稱加密:加密和解密使用不同的密鑰,成為公鑰和私鑰。數(shù)據(jù)用公鑰加密后必須用私鑰解密,數(shù)據(jù)用私鑰加密后必須用公鑰解密。
- 特點(diǎn):速度慢,CPU 開銷大
- 常見算法:RSA
- Hash:把任意長度數(shù)據(jù)經(jīng)過處理變成一個(gè)長度固定且唯一的字符串,無法反向解密成原始數(shù)據(jù)
- 特點(diǎn):驗(yàn)證數(shù)據(jù)完整性
- 常見算法:MD5、SHA1、SHA256
攻擊方式(傳輸過程中)
- 拒絕服務(wù):攻擊者讓目標(biāo)機(jī)器停止提供服務(wù)
- 信息泄露:攻擊者獲取用戶信息
- 中間人攻擊:攻擊者通過各種手段,在服務(wù)端發(fā)出的 HTTP | HTML 報(bào)文與顯示屏呈現(xiàn)出的 Web 頁面之間做一些手腳,篡改網(wǎng)頁的部分或者全部內(nèi)容,從而改變用戶在瀏覽器視窗中看到的內(nèi)容
- 重放攻擊: 攻擊者發(fā)送一個(gè)目的主機(jī)已接收過的包,來達(dá)到欺騙系統(tǒng)的目的,主要用于身份認(rèn)證過程,破壞認(rèn)證的正確性
HTTPS 實(shí)現(xiàn)安全數(shù)據(jù)傳輸
主要方案
- 服務(wù)器生成一對公鑰服和私鑰服,公鑰服給瀏覽器
- 瀏覽器做對稱加密,產(chǎn)生密鑰瀏,使用公鑰服加密密鑰瀏,發(fā)送給服務(wù)器
- 服務(wù)器接收到公鑰服加密的密鑰瀏,服務(wù)器使用私鑰服解密,從而得到密鑰瀏
- 服務(wù)器和瀏覽器使用密鑰瀏進(jìn)行交流
確保瀏覽器得到的是真正的公鑰服
根 CA + 上級 CA + CA 機(jī)構(gòu)
根 CA 擔(dān)保上級 CA,上級 CA 擔(dān)保 CA 機(jī)構(gòu)
當(dāng)一個(gè)網(wǎng)站要使用 HTTPS 時(shí)先需在一些國際認(rèn)證的 CA 機(jī)構(gòu)填寫網(wǎng)站信息申請證書,而這些 CA機(jī)構(gòu)還有上層 CA,最終有一個(gè)根 CA
上述三者都做對稱加密,分別得到
- 公鑰根CA + 私鑰根CA
- 公鑰上級CA + 私鑰上級CA
- 公鑰CA機(jī)構(gòu) + 私鑰CA機(jī)構(gòu)
私鑰根CA 加密 公鑰上級CA
私鑰上級CA 加密 公鑰CA機(jī)構(gòu)
私鑰CA機(jī)構(gòu) 加密 公鑰服
瀏覽器都會(huì)內(nèi)置根 CA 和一些頂級 CA 的證書
瀏覽器所要做的
- 根據(jù) 公鑰根CA 解密 私鑰根CA
- 根據(jù)解密出的 私鑰根CA 解密 公鑰上級CA
- 根據(jù)解密出的 公鑰上級CA 解密 私鑰上級CA
- 根據(jù)解密出的 私鑰上級CA 解密 公鑰CA機(jī)構(gòu)
- 根據(jù)解密出的 公鑰CA機(jī)構(gòu) 解密 私鑰CA機(jī)構(gòu)
- 根據(jù)解密出的 私鑰CA機(jī)構(gòu) 解密 公鑰服
至此瀏覽器得到真正的 公鑰服
說明了 12306 網(wǎng)站的 HTTPS 證書沒有機(jī)構(gòu)為其擔(dān)保,所以瀏覽器提示連接不安全
XSS 攻擊
XSS 攻擊是一種安全漏洞,攻擊者利用這種漏洞在網(wǎng)上注入惡意的客戶端代碼,詳細(xì)請看
避免方式
- 所有用戶輸入的地方都是不安全的,所以不要把用戶提交的東西作為 HTML 去運(yùn)行,即不使用
innerHTML
- JavaScript 中不要使用
eval()
CSRF(跨站請求偽造) 攻擊
原理
攻擊者構(gòu)造網(wǎng)站后臺某個(gè)功能接口的請求地址,誘導(dǎo)用戶去點(diǎn)擊或用特殊方法讓該請求地址自動(dòng)加載,用戶在登錄狀態(tài)下這個(gè)請求被服務(wù)端接受后會(huì)被誤以為是用戶合法的操作,對于 GET 形式的接口地址可輕易被攻擊,對于 POST 形式的接口地址也不是百分百安全,攻擊者可誘導(dǎo)用戶帶 Form 表單可用 POST 方式提交參數(shù)的頁面
避免方式
- 用戶提交數(shù)據(jù)時(shí) + 驗(yàn)證步驟
- 后端給前端傳輸?shù)臄?shù)據(jù)中,生成隨機(jī)數(shù),把隨機(jī)數(shù)使用 Set-Cookie 寫入到 Cookie 中,同時(shí)把隨機(jī)數(shù)寫到 Form 表單中(
<input type='hidden' CSRF='隨機(jī)數(shù)'
),當(dāng)用戶提交表單時(shí),服務(wù)器收到請求后查看 Form 表單中隨機(jī)數(shù)是否 === Cookie 中隨機(jī)數(shù)
性能優(yōu)化
性能優(yōu)化主要分為加載優(yōu)化 + 體驗(yàn)優(yōu)化兩方面
加載優(yōu)化
- 服務(wù)器網(wǎng)速要好,寬帶夠,使用 CDN
- 把所有資源壓縮,尤其是圖片壓縮,選擇合適的圖片大小,HTML、CSS、JS 壓縮
- 減少請求,生產(chǎn)環(huán)境資源打包合并
- 后端接口速度加快
- 利用緩存,能重復(fù)利用的都重復(fù)利用,Cache-Control + ETag
體驗(yàn)優(yōu)化
- 只給用戶暫時(shí)需要的東西,按需加載 + 懶加載
- 代碼性能優(yōu)化
- CSS3 動(dòng)畫優(yōu)先,其次是 JS 動(dòng)畫,transform > position + left > margin-left