相關概念
URI
URI 包含 URL 和 URN。
==請求和響應報文==
請求報文
響應報文
HTTP方法
- GET:獲取資源
- HEAD:獲取報文首部
- POST:傳輸實體主體
- PUT:上傳文件(自身不帶驗證機制,不安全)
- PATCH:對資源進行部分修改(允許部分修改,PUT只能完全替換)
- DELETE:刪除文件(不帶驗證機制)
- OPTIONS:查詢支持的方法
- CONNECT:要求在與代理服務器通信時建立隧道(使用 SSL(Secure Sockets Layer,安全套接層)和 TLS(Transport Layer Security,傳輸層安全)協議把通信內容加密后經網絡隧道傳輸。)
- TRACE:追蹤路徑(不用,容易受到 XST 攻擊)
HTTP狀態碼
鏈接管理
- 短連接與長連接
長連接只需要建立一次 TCP 連接就能進行多次 HTTP 通信。
- 從 HTTP/1.1開始默認是長連接的,如果要斷開連接,需要由客戶端或者服務器端提出斷開,使用 Connection : close;
- 在 HTTP/1.1之前默認是短連接的,如果需要使用長連接,則使用 Connection : Keep-Alive。
- 流水線
默認情況下,HTTP請求是按順序發出的,下一個請求只有在當前請求收到響應之后才會被發出。由于受到網絡延遲和帶寬的限制,在下一個請求被發送到服務器之前,可能需要等待很長時間。
流水線是在同一條長連接上連續發出請求,而不用等待響應返回,這樣可以減少延遲。
Cookie相關
HTTP 協議是無狀態的,主要是為了讓 HTTP 協議盡可能簡單,使得它能夠處理大量事務。HTTP/1.1 引入 Cookie 來保存狀態信息。
==Cookie 是服務器發送到用戶瀏覽器并保存在本地的一小塊數據==,它會在瀏覽器之后向同一服務器再次發起請求時被攜帶上,用于告知服務端兩個請求是否來自同一瀏覽器。由于之后每次請求都會需要攜帶 Cookie 數據,因此會帶來額外的性能開銷(尤其是在移動環境下)
- 用途
- 會話狀態管理(如用戶登錄狀態、購物車、游戲分數或其它需要記錄的信息)
- 個性化設置(如用戶自定義設置、主題等)
- 瀏覽器行為跟蹤(如跟蹤分析用戶行為等)
- 創建過程
服務器發送的響應報文包含 Set-Cookie 首部字段,客戶端得到響應報文后把 Cookie 內容保存到瀏覽器中。
HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
[page content]
客戶端之后對同一個服務器發送請求時,會從瀏覽器中取出 Cookie 信息并通過 Cookie 請求首部字段發送給服務器。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
- 分類
- ==會話期 Cookie==:瀏覽器關閉之后它會被自動刪除,也就是說它僅在會話期內有效。
- ==持久性 Cookie==:指定過期時間(Expires)或有效期(max-age)之后就成為了持久性的 Cookie。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
Session相關
除了可以將用戶信息通過 Cookie 存儲在用戶瀏覽器中,也可以利用 Session 存儲在服務器端,存儲在服務器端的信息更加安全。
==Session 可以存儲在服務器上的文件、數據庫或者內存中==。也可以將 Session 存儲在 Redis 這種內存型數據庫中,效率會更高。
使用 Session 維護用戶登錄狀態的過程如下:
- 用戶進行登錄時,用戶提交包含用戶名和密碼的表單,放入 HTTP 請求報文中;
- 服務器驗證該用戶名和密碼,如果正確則把用戶信息存儲到 Redis 中,它在 Redis 中的 Key 稱為 Session ID;
- 服務器返回的響應報文的 Set-Cookie 首部字段包含了這個 Session ID,客戶端收到響應報文之后將該 Cookie 值存入瀏覽器中;
- 客戶端之后對同一個服務器進行請求時會包含該 Cookie 值,服務器收到之后提取出 Session ID,從 Redis 中取出用戶信息,繼續之前的業務操作。
Cookie 與 Session 選擇
- Cookie 只能存儲 ASCII 碼字符串,而 Session 則可以存儲任何類型的數據,因此在考慮數據復雜性時首選 Session;
- Cookie 存儲在瀏覽器中,容易被惡意查看。Session存在服務器。如果非要將一些隱私數據存在 Cookie 中,可以將 Cookie 值進行加密,然后在服務器進行解密;
- 對于大型網站,如果用戶所有的信息都存儲在 Session 中,那么開銷是非常大的,因此不建議將所有的用戶信息都存儲到 Session 中。
通信數據轉發
- 代理
代理服務器接受客戶端的請求,并且轉發給其它服務器。
使用代理的主要目的是:
- 緩存
- 負載均衡
- 網絡訪問控制
- 訪問日志記錄
代理服務器分為正向代理和反向代理兩種:
- 用戶察覺得到正向代理的存在。
- 而反向代理一般位于內部網絡中,用戶察覺不到
- 網關
與代理服務器不同的是,網關服務器會將 HTTP 轉化為其它協議進行通信,從而請求其它非 HTTP 服務器的服務。
- 隧道
使用 SSL 等加密手段,在客戶端和服務器之間建立一條安全的通信線路。
==HTTPS==
==為什么有HTTP還要HTTPS==?
因為HTTP 有以下安全性問題:
- 使用明文進行通信,內容可能會被竊聽;
- 不驗證通信方的身份,通信方的身份有可能遭遇偽裝;
- 無法證明報文的完整性,報文有可能遭篡改。
==HTTPS 并不是新協議,而是讓 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信==,也就是說 HTTPS 使用了隧道進行通信。
通過使用 SSL,==HTTPS 具有了加密(防竊聽)、認證(防偽裝)和完整性保護(防篡改)==。
加密
- 對稱密鑰加密
加密和解密使用同一密鑰。
- 優點:運算速度快;
- 缺點:==無法安全地將密鑰傳輸給通信方==。
==常見的對稱加密算法有:DES、3DES、AES、PBE等==,這幾種算法安全行依次遞增。
- 非對稱密鑰加密
又稱公開密鑰加密(Public-Key Encryption),加密和解密使用不同的密鑰。
公開密鑰所有人都可以獲得,通信發送方獲得接收方的公開密鑰之后,就可以使用公開密鑰進行加密,接收方收到通信內容后使用私有密鑰解密。
非對稱密鑰除了用來加密,還可以用來進行簽名。因為私有密鑰無法被其他人獲取,因此通信發送方使用其私有密鑰進行簽名,通信接收方使用發送方的公開密鑰對簽名進行解密,就能判斷這個簽名是否正確。
- 優點:可以更安全地將公開密鑰傳輸給通信發送方;
- 缺點:==運算速度慢==。
==常用的非對稱加密算法有RSA和DEA==
- ==HTTPS采用的加密方式==
上面提到對稱密鑰加密方式的傳輸效率更高,但是無法安全地將密鑰 Secret Key 傳輸給通信方。而非對稱密鑰加密方式可以保證傳輸的安全性,因此我們可以利用非對稱密鑰加密方式將 Secret Key 傳輸給通信方。==HTTPS 采用混合的加密機制==,結合兩種加密方案:
- 使用非對稱密鑰加密方式,傳輸對稱密鑰加密方式所需要的 Secret Key,從而保證安全性;
- 接收方使用非對稱加密方式解密獲取到 Secret Key 后,再使用對稱密鑰加密方式進行通信,從而保證效率。(下圖中的 Session Key 就是 Secret Key)
認證
通過使用 證書 來對通信方進行認證。
數字證書認證機構(CA,Certificate Authority)是客戶端與服務器雙方都可信賴的第三方機構。
服務器的運營人員向 CA 提出公開密鑰的申請,CA 在判明提出申請者的身份之后,會對已申請的公開密鑰做數字簽名,然后分配這個已簽名的公開密鑰,并將該公開密鑰放入公開密鑰證書后綁定在一起。
進行 HTTPS 通信時,服務器會把證書發送給客戶端。客戶端取得其中的公開密鑰之后,先使用數字簽名進行驗證,如果驗證通過,就可以開始通信了。
完整性保護
SSL 提供報文摘要功能來進行完整性保護。
HTTP 也提供了 MD5 報文摘要功能,但不是安全的。例如報文內容被篡改之后,同時重新計算 MD5 的值,通信接收方是無法意識到發生了篡改。
HTTPS 的報文摘要功能之所以安全,是因為它結合了加密和認證這兩個操作。試想一下,加密之后的報文,遭到篡改之后,也很難重新計算報文摘要,因為無法輕易獲取明文。
==HTTPS防止中間人劫持==
- 概念:中間人攻擊(Man-in-the-middle attack,縮寫:MITM)是指攻擊者與通訊的兩端分別建立獨立的聯系,并交換其所收到的數據,使通訊的兩端認為他們正在通過一個私密的連接與對方直接對話,但事實上整個會話都被攻擊者完全控制。
使用中間人攻擊手段,必須要讓客戶端信任中間人的證書,如果客戶端不信任,則這種攻擊手段也無法發揮作用。
- 中間人攻擊原理
下面我們通過一個流行的MITM開源庫mitmproxy來分析中間人攻擊的原理。中間人攻擊的關鍵在于https握手過程的ClientKeyExchange,由于pre key交換的時候是使用服務器證書里的公鑰進行加密,如果用的偽造證書的公鑰,那么中間人就可以解開該密文得到pre_master_secret計算出用于對稱加密算法的master_key,從而獲取到客戶端發送的數據;然后中間人代理工具再使用其和服務端的master_key加密傳輸給服務端;同樣的服務器返回給客戶端的數據也是經過中間人解密再加密,于是完整的https中間人攻擊過程就形成了,一圖勝千言。
- 中間人攻擊的三種情況
我們現在常見的SSL中間人攻擊方式都是通過偽造、剝離SSL證書來實現的。因為SSL是為網絡通信提供安全及數據完整性的一種安全協議,它可以驗證參與通訊的一方或雙方使用的證書是否由權威受信任的CA機構頒發,并且能執行雙向身份認證,幾乎不可能會被攻破。
換句話說,如果有SSL中間人攻擊事件,并不是SSL協議或者SSL證書的問題,而是SSL證書的驗證環節。==中間人攻擊的前提條件是,沒有嚴格對證書進行校驗,或者人為的信任偽造證書==,因此以下場景正是最容易被用戶忽視的證書驗證環節:
第 一種:網站并沒有部署SSL證書,網站處于HTTP明文傳輸狀態。這種情況黑客可直接通過網絡抓包的方式,明文獲取傳輸數據。
第二種:黑客通過偽造SSL證書的方式進行攻擊,用戶安全意識不強選擇繼續操作。
第三種:黑客偽造SSL證書,網站/APP只做了部分證書(域名)校驗,導致假證書蒙混過關
https://www.cnblogs.com/wh4am1/p/6616856.html
==HTTPS 的缺點==
- 因為需要進行加密解密等過程,因此速度會更慢;
- 需要支付證書授權的高額費用。
HTTP/1.1新特性
- 默認是長連接
- 支持流水線
- 支持同時打開多個 TCP 連接
- 支持虛擬主機
- 新增狀態碼 100
- 支持分塊傳輸編碼
- 新增緩存處理指令 max-age
HTTP/2.0
HTTP/1.x 缺陷
HTTP/1.x 實現簡單是以犧牲性能為代價的:
- 客戶端需要使用多個連接才能實現并發和縮短延遲;
- 不會壓縮請求和響應首部,從而導致不必要的網絡流量;
- 不支持有效的資源優先級,致使底層 TCP 連接的利用率低下。
二進制分幀層
HTTP/2.0 將報文分成 HEADERS 幀和 DATA 幀,它們都是二進制格式的。
在通信過程中,只會有一個 TCP 連接存在,它承載了任意數量的雙向數據流(Stream)。
- 一個數據流(Stream)都有一個唯一標識符和可選的優先級信息,用于承載雙向信息。
- 消息(Message)是與邏輯請求或響應對應的完整的一系列幀。
- 幀(Frame)是最小的通信單位,來自不同數據流的幀可以交錯發送,然后再根據每個幀頭的數據流標識符重新組裝。
服務端推送
HTTP/2.0 在客戶端請求一個資源時,會把相關的資源一起發送給客戶端,客戶端就不需要再次發起請求了。例如客戶端請求 page.html 頁面,服務端就把 script.js 和 style.css 等與之相關的資源一起發給客戶端。
首部壓縮
HTTP/1.1 的首部帶有大量信息,而且每次都要重復發送。
HTTP/2.0 要求客戶端和服務器同時維護和更新一個包含之前見過的首部字段表,從而避免了重復傳輸。
不僅如此,HTTP/2.0 也使用 Huffman 編碼對首部字段進行壓縮。
==GET 和 POST 比較==
- 作用:GET 用于獲取資源,而 POST 用于傳輸實體主體。
- 參數:
- GET 的參數是以查詢字符串出現在 URL 中,因為 URL 只支持 ASCII 碼,因此 GET 的參數中如果存在中文等字符就需要先進行編碼。
- POST 的參數存儲在實體主體中,POST 參數支持標準字符集。
安全:安全的 HTTP 方法不會改變服務器狀態,也就是說它只是可讀的。
GET 方法是安全的,而 POST 卻不是,因為 POST 的目的是傳送實體主體內容,這個內容可能是用戶上傳的表單數據,上傳成功之后,服務器可能把這個數據存儲到數據庫中,因此狀態也就發生了改變。
安全的方法除了 GET 之外還有:HEAD、OPTIONS。
不安全的方法除了 POST 之外還有 PUT、DELETE。冪等性:冪等的 HTTP 方法,同樣的請求被執行一次與連續執行多次的效果是一樣的,服務器的狀態也是一樣的。換句話說就是,冪等方法不應該具有副作用(統計用途除外)。
所有的安全方法也都是冪等的。GET方法是冪等的,POST方法不是。數據長度:GET請求在URL中傳送的參數是有長度限制的(不同瀏覽器不同,2-64kb),而POST沒有。
數據包:GET產生一個TCP數據包;POST會產生兩個TCP數據包(Firefox不會)。
(對于GET方式的請求,瀏覽器會把http header和data一并發送出去,服務器響應200(返回數據);
而對于POST,瀏覽器先發送header,服務器響應100 continue,瀏覽器再發送data,服務器響應200 ok(返回數據)。)
參考鏈接:
https://github.com/CyC2018/CS-Notes/blob/master/notes/HTTP.md