導航
[深入01] 執行上下文
[深入02] 原型鏈
[深入03] 繼承
[深入04] 事件迴圈
[深入05] 柯里化 偏函式 函式記憶
[深入06] 隱式轉換 和 運算子
[深入07] 瀏覽器快取機制(http快取機制)
[深入08] 前端安全
[深入09] 深淺拷貝
[深入10] Debounce Throttle
[深入11] 前端路由
[深入12] 前端模組化
[深入13] 觀察者模式 釋出訂閱模式 雙向資料繫結
[深入14] canvas
[深入15] webSocket
[深入16] webpack
[深入17] http 和 https
[深入18] CSS-interview
[react] Hooks
[部署01] Nginx
[部署02] Docker 部署vue專案
[部署03] gitlab-CI
前置知識
一些單詞
protocol:協議
permanent:永久的
permanently:永久地
temporary:暫時的
grammar:語法
複製程式碼
TCP/IP協議 - 應用層,傳輸層,網路層,資料鏈路層
- 應用層:HTTP FTP TELNET SMTP DNS等協議
- 傳輸層:TCP協議 UDP協議
- 網路層:IP協議 ICMP協議等
- 資料鏈路層
( TCP和UDP ) 傳輸層協議使用 ( IP協議 )網路層協議 從一個網路傳送資料包到另一個網路
- 把 ( IP ) 想像成一種 ( 高速公路 ),它允許其它協議在上面行駛並找到到其它電腦的出口。
- ( TCP和UDP ) 是高速公路上的 ( “卡車” )
- 卡車攜帶的 ( 貨物 ) 就是像 ( HTTP ),檔案傳輸協議FTP這樣的協議
TCP首部圖解
- 總結
- Ack = Seq + 1 ---------------------- 確認號 = 序號 + 1
- 序號Seq ( 簡稱ISN )
- 確認號Ack
- 標誌位:
- SYN新建一個連結
- FIN釋放一個連結
- ACK為1時Seq序號才有效
TCP三次握手
三次握手:指的是建立TCP連結時,需要客戶端和服務端總的傳送的三個包
- 第一次握手
- 客戶端傳送一個 ( 標誌位SYN=1,序號Seq=x ) 的 ( 連線包 ) 到伺服器
- SYN=1表示新建連結
- 客戶端狀態:由 CLOSED狀態 => SYN_SENT狀態
- 客戶端傳送一個 ( 標誌位SYN=1,序號Seq=x ) 的 ( 連線包 ) 到伺服器
- 第二次握手
- 伺服器傳送一個 ( 標誌位SYN=1,ACK=1,序號Seq=y,確認號Ack=x+1) 的 ( 確認包 ) 給客戶端
- Ack = Seq + 1
( 確認號 = 序號 + 1 )
- 服務端狀態:由 CLOSED狀態 => SYN_RCVD狀態
- Ack = Seq + 1
- 伺服器傳送一個 ( 標誌位SYN=1,ACK=1,序號Seq=y,確認號Ack=x+1) 的 ( 確認包 ) 給客戶端
- 第三次握手
- 客戶端傳送一個 ( 標誌位SYN=0,ACK=1,序號Seq=x+1,確認號Ack=y+1) 的 ( 確認包 ) 給伺服器
- established:是建立的意思
- 客戶端和服務端狀態都變成 ESTABLISHED 狀態
- 客戶端傳送一個 ( 標誌位SYN=0,ACK=1,序號Seq=x+1,確認號Ack=y+1) 的 ( 確認包 ) 給伺服器
TCP建立連結 - 為什麼需要第三次握手
為什麼只有三次握手,才能確認雙方的傳送和接收能力是否正常,而兩次卻不可以??
- 第一次握手:
- 客戶端傳送連線包,服務端收到了
- ( 服務端 ) 就能得出結論:( 客戶端的傳送能力,服務端的接收能力是正常的 )
- 第二次握手
- 服務端傳送確認包,客服端收到了
- ( 客戶端 ) 就能得出結論:( 服務端的接收、傳送能力,客戶端的接收、傳送能力是正常的 )
- 注意:此時服務端並不能確認客戶端的接收能力是否正常
- 第三次握手
- 客戶端傳送確認包,服務端收到了
- ( 服務端 ) 就能得出結論:( 客戶端的接收、傳送能力,和服務端的接收、傳送能力都是正常的 )
- 總結為什麼需要三次握手:
- 為了實現可靠資料傳輸, TCP 協議的通訊雙方都必須維護一個序列號, 標識傳送出去的資料包哪些已經被對方收到
- 三次握手的過程即是通訊雙方相互告知序列號起始值, 並確認對方已經收到了序列號起始值的必經步驟
- 如果只是兩次握手, 至多隻有連線發起方的起始序列號能被確認, 另一方選擇的序列號則得不到確認,也就是上面每次握手分析的,如果兩次握手,服務端是沒法確認客戶端的接收能力是正常的
- 防止已失效的連線請求又傳送到伺服器端,因而產生錯誤
四次揮手
- 標誌位:FIN表示釋放一個連結
- 注意:客戶端和服務端都可以主動發起揮手動作
- established:建立的意思 ( ESTABLISHED )
- 過程:( 假設由客戶端發起,標誌位FIN=1表示釋放連結 )
- 第一次揮手
- 客戶端傳送一個 ( 標誌位FIN=1,序號Seq=u ) 的 ( 釋放包 ) 到伺服器
- 客戶端狀態:由 ESTABLISHED狀態 => FIN_WAIT1狀態
- 表明的是:主動方(客戶端)的報文傳送完了,但是主動方(客戶端)還是可以接收報文
- 第二次揮手
- 伺服器返回一個 ( 標誌位ACK=1,確認號Ack=u+1,序號Seq=v ) 的 ( 確認包 ) 到客戶端
- 服務端狀態:由 ESTABLISHED狀態 => COLSE_WAIT狀態
- 第三次次揮手
- 伺服器傳送一個 ( 標誌位FIN=1,ACK=1,確認號Ack=u+1,序號Seq=w ) 的 ( 釋放包 ) 到客戶端
- 服務端狀態:由 COLSEWAIT狀態 => LAST_ACK狀態
- 表明的是:主動方(服務端)的報文傳送完了,但是主動方(服務端)還是可以接收報文
- 第四次次揮手
- 客戶端送一個 ( 標誌位ACK=1,確認號Ack=w+1, 序號Seq=u+1 ) 的 ( 確認包 ) 到服務端
- 客戶端狀態:由 FIN_WAIT2狀態 => TIME_WAIT狀態
- 注意:
- 客戶端通常是主動關閉,進入TIME_WAIT狀態
- 服務端通常是被動關閉,不會進入TIME_WAIT狀態
TIME_WAIT狀態 - 2MSL狀態
- TIME_WAIT狀態也稱為2MSL等待狀態
- 每個具體TCP實現必須選擇一個報文段最大生存時間MSL(Maximum Segment Lifetime),它是任何報文段被丟棄前在網路內的最長時間。
為什麼第四次揮手後,客戶端要進入TIME_WAIT狀態,而不是直接關閉
- 因為要確保伺服器是否收到了Ack確認報文,即在2MSL時間內沒有再收到服務端的FIN報文,證明已經收到ACK
- 如果沒有收到的話,伺服器會重新發 FIN 報文給客戶端,客戶端再次收到 ACK 報文之後,就知道之前的 ACK 報文丟失了,然後再次傳送 ACK 報文。
- TIME_WAIT 持續的時間至少是一個報文的來回時間。一般會設定一個計時,如果過了這個計時沒有再次收到 FIN 報文,則代表對方成功就是 ACK 報文,此時處於 CLOSED 狀態。
一些重要的HTTP狀態碼
100 Continue ------------------------- 客戶端應繼續請求
101 Switching Protocols -------------- 切換協議,協議升級
200 ok ------------------------------- 請求被正常處理
204 no content ----------------------- 請求處理成功,但沒有資源可以返回
206 partial content ------------------ 請求部分資源
301 moved permanently ---------------- 永久重定向,需要變更書籤引用
302 Found ---------------------------- 臨時重定向
303 set other ------------------------ 臨時重定向,應採用 GET 方法獲取資源
304 not modified --------------------- 資源未被修改,協商快取
307 Temporary Redirect --------------- 臨時重定向
400 bad request ---------------------- 錯誤的請求
401 unauthorized --------------------- 認證失敗 ------------------------- (未授權)
403 forbidden ------------------------ 認證成功,但許可權不夠 ------------- (許可權不夠)
404 not found ------------------------ 資源未找到
405 method not allowed --------------- 請求方法錯誤
500 Internal Server Error ------------ 服務端錯誤
502 Bad Gateway ---------------------- 閘道器錯誤
503 Service Unavailable -------------- 伺服器過載
複製程式碼
HTTP
HTTP的缺點
- 通訊使用 明文(不加密),內容可能會被 竊聽
- 不驗證通訊方的 身份,因此有可能遭遇 偽裝
- 無法證明報文的 完整性,所以有可能已遭 篡改
HTTP是 明文傳播,可能會遭到 竊聽 |
- http本身不具備加密功能,報文使用明文傳播
- 為什麼設計成不加密:
- TCP/IP 協議族的工作機制,通訊內容在所有的通訊線路上都有 可能遭到窺視。
- 即使已經過加密處理的通訊,也會被窺視到通訊內容,這點和未 加密的通訊是相同的。只是說如果通訊經過加密,就有可能讓人 無法破解報文資訊的含義,但加密處理後的報文資訊本身還是會 被看到的
加密的物件有哪些 - (加密處理防止被竊聽)
- 通訊線路的加密 - 安全的通訊線路
- 通訊內容的加密 - 內容有被篡改的風險
通訊線路的加密
- http 通過和 SSL(secure socket layer 安全套接層) 或者和 TLS(transport layer security 安全層傳輸協議)的組合使用,來加密http的通訊內容
通訊內容的加密
- 內容仍有被篡改的風險
HTTP不驗證通訊雙方的身份,可能會遭遇偽裝 |
- HTTP 協議中的請求和響應不會對通訊方進行確認。
- 伺服器是否就是傳送請求中 URI 真正指定的主機
- 返回的響應是否真的返回到實際提出請求的客戶端,等類似問題。
不驗證通訊雙方的隱患
- 無法確定響應的伺服器,就是要請求的目標伺服器
- 無法確定響應內容是是否真正傳送給了請求時的客服端
- 無法確定正在通訊的對方是否具備訪問許可權。如果Web伺服器上儲存著重要的資訊,只想發給特定使用者通訊的許可權。
- 無法判定請求是來自何方、出自誰手
- 即使是無意義的請求也會照單全收。無法阻止海量請求下的 DoS 攻擊(Denial of Service,拒絕服務攻擊)
- 注意:http協議無法確定通訊方,但是SSL可以
- SSL不僅提供加密處理,而且還使用了一種被稱為證書的手段, 可用於確定方
- 證書由值得信任的第三方機構頒發,用以證明伺服器和客戶端是 實際存在的
HTTP無法驗證報文的完整性,可能會被篡改 |
- 完整性指資訊的準確度
- 接收到的內容可能有誤
什麼是中間人攻擊
- 像這樣,請求或響應在傳輸途中,遭攻擊者攔截並篡改內容的攻擊稱為中間人攻擊
- (Man-in-the-Middle attack,MITM)。
使用http協議確認確認報文完整性的方法
- MD5 和 SHA-1 等雜湊值校驗的方法
- 以及用來確認檔案的數字簽名方法。
HTTP報文 = 報文首部 + 空行 + 報文主體
請求報文首部 = 請求行 + 請求頭
響應報文首部 = 響應行 + 響應頭
- 用於http協議互動的資訊被稱為http報文
- 請求報文:客戶端的報文
- 響應報文:服務端的報文
- http報文:由多行資料構成的字串文字
HTTPS
HTTPS = HTTP + 加密 + 認證 + 完整性保護
- ssl是獨立與http協議的,所以其他應用層的協議也可以使用ssl
HTTPS的加密方式 - 混合加密,即對稱加密和非對稱加密一起使用
- https採用混合加密
-
在交換金鑰環節:使用公開加密 - (非對稱加密) -
之後的建立通訊,交換報文階段:使用共享加密 - (對稱加密) - ( 非對稱加密 ) 的處理速度要比 ( 對稱加密 ) 慢,所以各有優勢,所以https採用組合加密
-
公開金鑰加密方式 - 無法證明公開金鑰本身就是貨真價實的公開金鑰
證明公開金鑰正確定的證書
- 公開金鑰加密存在的問題
- 無法證明公開金鑰就是貨真價實的公開金鑰, 因為公開金鑰在傳播過程中可能被替換
問題:如何解決公開加密方式的公鑰的安全性 ????? 解決:數字證書機構頒發的 ( 公開金鑰證書 )
數字證書機構的業務流程
- 伺服器申請公開金鑰證書
- 證書認證機構對已申請的 ( 公開金鑰 ) 做 ( 數字簽名 ),生成 ( 公鑰證書 )
- 伺服器將公鑰證書發給客戶端
- 客服端使用證書結構的 ( 公開金鑰 ) 對 ( 公鑰證書的數字簽名 ) 進行驗證
- 驗證通過
- 說明伺服器的公鑰是證書機構頒發的公鑰
- 伺服器的公鑰值得信賴
- 驗證通過
https的通訊過程 - SSL握手過程
-
名稱解釋:
- handshake:握手
- certificate:證書
- cipher:密碼
- Suite:一套
- cipher suite:密碼元件
- spec:規格
- exchange:交換
- ClientKeyExchange
- ChangeCipherSpec:改變密碼規格,即非對稱加密交換公共金鑰後,使用對稱加密通訊
-
SSL握手過程 - 注意結合認證,組合加密一起來理解
-
(1) ( 客戶端 ) 通過傳送 ( client hello 報文 ) 開始 SSL 通訊
- 報文中包含:( SSL版本 ),( 加密元件列表 )
- 加密元件列表cipher suite包含:加密演算法,金鑰長度等
-
(2) ( 服務端 ) 傳送 ( erver Hello 報文 ) 作為應答
- 報文中同樣包含:( SSL版本 ),( 加密元件列表 )
- ( 伺服器 ) 的加密元件內容是從接收到的 ( 客戶端 ) 加密元件內 ( 篩選 ) 出來的
-
(3) ( 伺服器 ) 傳送 ( certificate ) 加密報文,報文中包含 ( 公開金鑰證書 )
-
(4) ( 伺服器 ) 傳送 ( Server Hello Done ) 報文通知客戶端,最初階段的 ( SSL握手協商,即第一次SSL握手結束 ) 部分結束
-
(5) 第一次SSL握手結束後,( 客戶端 ) 傳送 ( Client Key Exchange ) 報文作為回應
- 報文中包含:Pre-Master secret 隨機密碼串,該報文使用3中的公共金鑰證書加密
-
(6) ( 客戶端 ) 繼續傳送 ( Change Cipher Spec ) 報文
- 該報文會提示伺服器,在此報文之後的通訊會採用 Pre-master secret 金鑰加密
-
(7) ( 客戶端 ) 傳送 ( Finished ) 報文
- 該報文包含連線至今,全部報文的整體校驗值
- 這次握手協商是否成功,要以伺服器是否能夠正確解密該報文作為判斷標準
-
(8) ( 伺服器 ) 同樣傳送 ( Change Cipher Spec ) 報文
-
(9) ( 伺服器 ) 同樣傳送 ( Finished ) 報文
-
(10) 傳送HTTP請求,服務端和客戶端的Finished報文交換完畢之後,SSL連線就算建立完成,通訊會受到 SSL 保護
- 從此處開始進行應用層的通訊,即傳送 HTTP 請求
-
(11) 響應HTTP請求
-
(12) 最後由客戶端斷開連線。斷開連線時,傳送 close_notify 報文。
url到頁面顯示過程
- DNS域名解析 // 將域名解析成IP地址
- 建立TCP連結 // 三次握手
- 客戶端發起HTTP請求
- 伺服器處理請求,並返回HTTP報文
- 瀏覽器解析渲染頁面
- 斷開TCP連結 // 四次揮手
url到頁面顯示的過程
1. DNS域名解析
- DNS是 ( domain name system ) 域名系統的縮寫
- 將域名解析成ip地址
- 一個域名對應一個以上的ip地址
- 為什麼要將域名解析成ip地址?
- 因 ( 為TCP/IP網路 ) 是通過 ( ip地址 ) 來確定 ( 通訊物件 ),不知道ip就無法將訊息傳送給對方
- DNS域名解析的過程:// 遞迴查詢和迭代查詢
1. ( 瀏覽器 ) 中查詢 DNS 快取,有則進入建立tcp連結階段,下面同理
2. ( 本機的系統 )中查詢 DNS 快取
3. ( 路由器 ) 中查詢 DNS 快取
4. ( 運營商伺服器 ) 中查詢 DNS 快取
5. 遞迴查詢 // 根域名/一級域名/二級域名 ....blog.baidu.com
- .com
- .baidu
- blog
- 還未找到就報錯
2. 建立tcp連結 // 三次握手
- 第一次握手
- 客服端傳送一個 標誌位SYN=1,序號Seq=x的連結包給服務端
- SYN:表示發起一個新連結,( Synchronize Sequence Numbers )
- Seq:序號是隨機的
- 第二次握手
- 服務端傳送一個 標誌位SYN=1,ACK=1,確認號Ack=x+1,序號Seq=y的確認包給客戶端
- 標誌位 ACK 表示響應
- 第三次握手
- 客戶端傳送一個 SYN=0,ACK=1,確認號Ack=y+1,序號Seq=x+1的確認包給伺服器
- 為什麼需要三次握手
- 之所以要第三次握手,主要是因為避免無效的連線包延時後又傳送到伺服器,造成伺服器以為又要建立連結的假象,造成錯誤
3. 客戶端傳送http請求
4. 服務端處理請求,並返回http響應報文
5. 瀏覽器解析渲染
- 遇見HTML標記,瀏覽器呼叫HTML解析器,解析成Token並構建DOM樹
- 遇見style/link標記,瀏覽器呼叫css解析器,解析成CSSOM樹
- 遇見script標記,瀏覽器呼叫js解析器,處理js程式碼(繫結事件,可能會修改DOM tree 和 CSSOM tree)
- 將DOM 和 CSSOM 合併成 render tree
- 根據render tree計算佈局(佈局)
- 將各個節點的顏色繪製到螢幕上(渲染)
6. 斷開TCP連結 // 四次揮手,( FIN : 表示釋放連結 )
- 第一次揮手:瀏覽器發起,告訴伺服器我請求報文傳送完了,你準備關閉吧
- 第二次揮手:伺服器發起,告訴瀏覽器我請求報文接收完了,我準備關閉了,你也準備吧
- 第三次揮手:伺服器發起,告訴瀏覽器,我響應報文傳送完了,你準備關閉吧
- 第四次揮手:瀏覽器發起,告訴伺服器,我響應報文接收完了,我準備關閉了,你也準備吧
- 先是伺服器先關閉,再是瀏覽器關閉
複製程式碼
TCP 和 UDP 的區別
-
TCP面向連結(可靠性高),UDP無連線(可靠性低)
HTTP1.0 和 HTTP1.1 的區別
HTTP1.0
- 無狀態:伺服器不跟蹤不記錄請求過的狀態
- 無連線:瀏覽器每次請求都要重新建立連結
HTTP1.0
(1) 無狀態
1. 伺服器不跟蹤記錄請求過的狀態
2. 對於無狀態的特性可以藉助 ( cookie/session ) 機制來做 ( 身份認證 ) 和 ( 狀態記錄 )
(2) 無連線
- 無連線導致的效能缺陷主要有兩種:
- 無法複用連結
- 每次傳送請求,都需要進行tcp連結,即三次握手和四次揮手,使得網路的利用率極低
- 對頭阻塞
- http1.0規定,在前一個請求響應到達之後,下一個請求才能傳送,如何前一個請求阻塞,後面的就都會阻塞
複製程式碼
HTTP1.1
HTTP1.1解決HTTP1.0的效能缺陷
- 長連線:新增Connection欄位,可以設定 keep-alive 使保持連結不斷開
- 管道化:基於長連線,管道化可以不等第一個請求響應,繼續傳送後面的請求,但是響應的順序還是要按請求的順序返回
- 快取處理:新增 cache-control 欄位
- 斷點續傳
HTTP1.1
(1) 長連線
- HTTP1.1預設保持長連線,資料傳輸完成,保持tcp連結不斷開,繼續使用這個通道傳輸資料
(2) 管道化
- http1.0
- 請求1 > 響應1 --> 請求2 > 響應2 --> 請求3 > 響應3
- http1.1
- 請求1 --> 請求2 --> 請求3 > 響應1 --> 響應2 --> 響應3
- 雖然管道化一次可以傳送多個請求,但響應仍然是順序返回,仍然無法解決對頭阻塞的問題
(3) 快取處理
- HTTP1.1新增 Cache-Control 欄位
- http1.0 => expires => 是一個絕對時間點,用GMT時間格式
- http1.1 => Cache-Control => 是一個相時時間段,以秒為單位
- Cache-control: no-cache,private,max-age=123123
- no-cache:不使用強快取,使用協商快取
- max-age: 一個時間段,單位是秒
- public:允許所有伺服器快取該資源
- private:表示該資源僅僅屬於發出請求的終端使用者,這將禁止中間伺服器(如代理伺服器)快取此類資源
對於包含使用者個人資訊的檔案,可以設定private
- Expires 和 Cache-Control 對比
- 如果同時開啟,Cache-Control 的優先順序高於 Expires
- expires是一個用GMT時間表示的時間點,Cach-Control是用秒錶示的時間段,都是和瀏覽器本地時間做對比
- Cache-Control 比 Expires 更加精確
(4) 斷點續傳
- 請求頭:Range
- 響應頭:Content-Range
- 原理
- 在上傳/下載資源時,如果資源過大,將其分割為多個部分,分別上傳/下載
- 如果遇到網路故障,可以從已經上傳/下載好的地方繼續請求,不用從頭開始,提高效率
複製程式碼
HTTP2.0
- 二進位制分幀
- 多路複用:在共享TCP連結的基礎上同時傳送請求和響應
- 頭部壓縮
- 伺服器推送:伺服器可以額外的向客戶端推送資源,而無需客戶端明確的請求
HTTP2.0
(1) 二進位制分幀
- 將所有傳輸的資訊分割為更小的訊息和幀,並對它們採用二進位制格式的編碼
(2) 多路複用
- 基於二進位制分幀
- 在同一域名下所有訪問都是從同一個tcp連線中走,http訊息被分解為獨立的幀,亂序傳送,服務端根據識別符號和首部將訊息重新組裝起來
複製程式碼
資料
HTTP和HTTPS簡介 juejin.im/post/5c6e58…
三次握手 juejin.im/post/5ca95e…
三次握手四次揮手 juejin.im/post/5cb932…
TCP報文 juejin.im/post/5a0444…
為什麼需要三次握手大白話 github.com/jawil/blog/…
四次揮手 juejin.im/post/5d9c28…
URL到頁面渲染 juejin.im/post/5c3401…
TCP和UDP:juejin.im/post/5a326c…
HTTP1.0 HTTP1.1 HTTP2.0 github.com/Advanced-Fr…
關於三次握手與四次揮手面試官想考我們什麼? juejin.im/post/5ccd0d…