- 靚仔靚女們大家好,我們又見面了,:java小杰要加油,這周來分享一篇關(guān)于
HTTP
協(xié)議相關(guān)的文章- 看完此文可以對
- HTTP報文格式、HTTP各種請求頭,HTTP響應(yīng)碼、 cookie屬性以及HTTPS為什么安全(涉及到三種加密方式) 有個清晰的認知
- 全文五千來字,強烈建議收藏,鞏固基礎(chǔ)
- 若文中涉及到的知識點有所偏差的話,還請大佬們指出,小杰感激不盡,沖沖沖!~
- 話不多說,直接開搞
HTTP簡介
- 超文本傳輸協(xié)議(Hypertext Transfer Protocol,HTTP)是一個簡單的請求-響應(yīng)協(xié)議,它通常運行在TCP之上。它指定了客戶端可能發(fā)送給服務(wù)器什么樣的消息以及得到什么樣的響應(yīng)
- 現(xiàn)在主要應(yīng)用 http1.1 協(xié)議
- http是無狀態(tài)協(xié)議,不會保存多次請求之間的關(guān)系,使用
cookie
做狀態(tài)管理 - 持久連接節(jié)省通信量(HTTP1.1和部分HTTP1.0)
- 通過請求方法告知服務(wù)器意圖,
get
,post
等
HTTP報文
- 用于HTTP協(xié)議交互的信息叫做HTTP報文
- 報文由報文首部和報文主體來組成,其中由空行分割
- 請求報文和響應(yīng)報文的報文結(jié)構(gòu)不一樣,其中最大的區(qū)別就是在報文首部中,各有各的特定的首部
- 報文首部:服務(wù)器或者客戶端需要處理的請求或者響應(yīng)的內(nèi)容及其屬性
- 報文主體:被發(fā)送的數(shù)據(jù)
HTTP請求報文結(jié)構(gòu)
- 由客戶端發(fā)送的報文叫做請求報文
- 請求行:包含用于請求的方法,請求URI和HTTP版本
- 請求首部字段:請求報文里特有的字段(后文會提到)
- 通用首部字段:請求報文和響應(yīng)報文都會用到的首部
- 實體首部字段:針對請求報文的實體部分使用的首部
- 其他:可能包含HTTP的RFC里未定義的首部(如Cookie等)
HTTP響應(yīng)報文結(jié)構(gòu)
- 由服務(wù)端發(fā)送的報文叫做響應(yīng)報文
- 狀態(tài)行:包含表明響應(yīng)結(jié)果的狀態(tài)碼,原因短語和HTTP版本
- 響應(yīng)首部字段:響應(yīng)報文里特有的字段(后文會提到)
- 通用首部字段:請求報文和響應(yīng)報文都會用到的首部
- 實體首部字段:針對響應(yīng)報文的實體部分使用的首部
- 其他:可能包含HTTP的RFC里未定義的首部(如Set-Cookie等)
注:若HTTP首部字段重復(fù)了的話,不同的瀏覽器處理機制不一樣
- 有些瀏覽器會優(yōu)先處理第一次出現(xiàn)的字段
- 有些瀏覽器會優(yōu)先處理最后一次出現(xiàn)的字段
HTTP響應(yīng)碼
2xx 成功
2xx的響應(yīng)結(jié)果就代表請求被正常處理了
- 200 OK:表示客戶端發(fā)來的請求被服務(wù)器正常處理了
- 204 Not Content:請求被成功處理,但是返回的響應(yīng)報文不包含實體的主體部分
- 206 Partial Content:客戶端進行范圍請求,而服務(wù)器重新執(zhí)行了這部分的GET請求
3xx 重定向
3xx的響應(yīng)結(jié)果就表明瀏覽器需要執(zhí)行某些特殊的處理以正確處理請求
- 301 Moved Permanently:永久重定向。表示請求的資源已經(jīng)被分配了新的URI,以后應(yīng)該使用新的URI
- 302 Found:臨時重定向。代表資源只是暫時的移動了以后還可能會移動為新的URI
- 303 See Other:由于請求對應(yīng)的資源存在著另一個URI,應(yīng)使用GET方法定向獲取請求的資源
- 304 Not Modified:客戶端發(fā)送附帶條件(請求首部中if開頭的屬性中的一種)的請求的時候,服務(wù)端允許訪問資源,但是那些請求并沒有滿足,直接返回304,即服務(wù)端資源未改變,可以直接使用客戶端未過期的緩存,304返回時,不包含任何響應(yīng)的主體部分(雖然被劃分為3xx里,但是和重定向沒有任何關(guān)系)
4xx 客戶端錯誤
4xx的響應(yīng)結(jié)果就表明客戶端是發(fā)生錯誤的原因所在
- 400 Bad Requset:請求報文中存在語法錯誤,請修改請求內(nèi)容后再發(fā)送請求
- 401 Unauthorized:客戶端未認證授權(quán)
- 403 Forbidden:服務(wù)端禁止客戶端訪問此資源
- 404 Not Found:URL寫錯了,找不到此路徑
5xx 服務(wù)器錯誤
5xx的響應(yīng)結(jié)果就表明服務(wù)器本身發(fā)生錯誤
- 500 Internal Server Error:服務(wù)器內(nèi)部故障,可能是bug導(dǎo)致的
-
503 Service Unavaliable:服務(wù)器暫時不可用(停機維護或者超負載),如果事先知道解除這種情況所需的時間,最好寫入響應(yīng)頭中的
Retry-After
這個字段再返回給客戶端
HTTP報文首部
HTTP1.1 規(guī)定了 以下47種首部字段
通用首部 (共9種)
首部字段 | 解釋 |
---|---|
1. Cache-Control | 控制緩存的行為 |
2. Connection | 逐跳首部、連接的管理 |
3. Date | 創(chuàng)建報文的日期和時間 |
4. Pragma | 報文指令 |
5. Trailer | 報文末端的首部一覽 |
6. Transfer-Encoding | 指定報文主體的傳輸編碼方式 |
7. Upgrade | 升級為其他協(xié)議 |
8. Via | 代理服務(wù)器的相關(guān)信息 |
9. Warning | 錯誤通知 |
下面我們來看挑幾個重要的屬性來看下~
- Connection 他有兩個作用
- 控制不再轉(zhuǎn)發(fā)給代理的首部字段
GET / HTTP/1.1
Upgrade: HTTP/1.1 // 就會把次字段刪除后再從代理服務(wù)器轉(zhuǎn)發(fā)出去
Connection: Upgrade // 不再轉(zhuǎn)發(fā)的首部字段名
- 管理持久鏈接(這個比較常見)
- HTTP/1.1默認連接都是持久連接
Connction: Keep-Alive
- 當(dāng)服務(wù)器想斷開的時候,需要指定
Connction: close
- HTTP/1.1默認連接都是持久連接
- Pragme :是
HTTP/1.1
之前版本遺留的字段,僅僅是為了與HTTP/1.0向后兼容而定義-
Pragm:no-cache
:通用首部字段,在請求頭中,表示所有的中間服務(wù)器不返回緩存的資源 - 可是所有的中間服務(wù)器都以
HTTP/1.1
為基準的話,可以直接采用Cache-Control:no-cache
- 所以一般會發(fā)送兩個字段
Cache-Control:no-cache
Pragm:no-cache
-
請求報文首部 (共19種)
首部字段 | 解釋 |
---|---|
1.Accrpt | 用戶代理可處理的媒體類型 |
2.Accrpt-Charset | 優(yōu)先的字符集 |
3.Accept-Encoding | 優(yōu)先的內(nèi)容編碼 |
4.Accept-Language | 優(yōu)先的語言(自然語言) |
5.Authorization | web認證信息 |
6.Expect | 期待服務(wù)器的特定行為 |
7.From | 用戶的電子郵箱地址 |
8.Host | 請求資源所在服務(wù)器 |
9.If-Match | 比較實體標(biāo)記(ETag) |
10.If-Modified-Since | 比較資源的更新時間 |
11.If-None-Match | 比較實體標(biāo)記(與If-Match相反) |
12.If-Range | 資源未更新時發(fā)送實體Byte的范圍請求 |
13.If-Unmodified-Since | 比較資源的更新時間(與If-Modified-Since相反) |
14.Max-Forwards | 最大傳輸逐跳數(shù) |
15.Proxy-Authorization | 代理服務(wù)器要求客戶端的認證信息 |
16.Range | 實體的字節(jié)范圍要求 |
17.Referer | 對請求中URI的原始獲取方 |
18.TE | 傳輸編碼的優(yōu)先級 |
19.User-Agent | HTTP客戶端程序的信息 |
-
If-Match:只有當(dāng)
If-Match
字段值跟ETag
值匹配一致時,服務(wù)器才會接受請求- 它會告知服務(wù)器匹配資源所用的實體標(biāo)記(ETag)值,這時服務(wù)器無法使用弱ETag值
- 僅當(dāng)兩者一致時才會執(zhí)行請求,否則返回
412 Precondition Failed
的響應(yīng) - 還可以使用 * 號指定
If-Match
的字段值,如果這樣的話,那么服務(wù)器將會忽略ETag的值,只要資源存在就處理請求。
-
If-Modified-Since :
- 若資源更新時間確實在此字段指定時間之后的話,則處理該請求,否則返回
304 Not Modified
- 用于確認代理或客戶端擁有本地資源的有效性,若想獲取資源的更新日期時間的話可以通過確認首部字段
Last-Modified
來確定
- 若資源更新時間確實在此字段指定時間之后的話,則處理該請求,否則返回
-
If-None-Match
- 只有在
If-None-Match
的字段值與ETag值不一致時,才可以處理該請求,與前文中提到的If-Match
作用相反
- 只有在
-
If-Range
- 他告知服務(wù)器若指定的
If-Range
字段值(ETag值或者時間)和請求資源的ETag值或時間一致時,則作為范圍請求處理,否則,返回全體資源
- 他告知服務(wù)器若指定的
-
If-Unmodified-Since
- 指定的請求資源只有在字段值內(nèi)指定的日期時間之后未發(fā)生更新,才會執(zhí)行這個請求,否則,返回
412 Precondition Failed
狀態(tài)響應(yīng),與If-Modified-Since
作用相反
- 指定的請求資源只有在字段值內(nèi)指定的日期時間之后未發(fā)生更新,才會執(zhí)行這個請求,否則,返回
-
Max-Forwards
- 每次請求轉(zhuǎn)發(fā)時數(shù)值減一,直到0時返回響應(yīng)
- 有可能這個請求經(jīng)過了多臺服務(wù)器代理轉(zhuǎn)發(fā),如果突然間請求出現(xiàn)了什么問題導(dǎo)致轉(zhuǎn)發(fā)失敗,而客戶端不知道,此時就可以用此屬性來定位問題,這個時候我們就可以掌握一個出問題的轉(zhuǎn)發(fā)路徑,從而方便進一步的排查問題。
-
Range:
- 對于只需要獲取部分資源的范圍請求,
Range
字段可以指定獲取資源范圍Range: bytes=10001-20000
- 例子中表示請求獲取從第10001字節(jié)到20000字節(jié)的資源
- 服務(wù)器處理請求后會返回
206 Partial Content
的響應(yīng)。無法處理時,則會返回狀態(tài)碼200 OK
的響應(yīng)及其全部資源
- 對于只需要獲取部分資源的范圍請求,
響應(yīng)報文首部 (共9種)
首部字段名 | 解釋 |
---|---|
1.Accept-Ranges | 是否接受字節(jié)范圍請求 |
2.Age | 推算資源創(chuàng)建經(jīng)過時間 |
3.ETag | 資源的匹配信息 |
4.Location | 令客戶端重定向至指定URI |
5.Proxy-Authenticate | 代理服務(wù)器對客戶端的認證信息 |
6.Retry-After | 對再次發(fā)起請求的時機要求 |
7.Server | HTTP服務(wù)器的安裝信息 |
8.Vary | 代理服務(wù)器緩存的管理信息 |
9.WWW-Authenticate | 服務(wù)器對客戶端的認證信息 |
-
Accept-Ranges
-
Accept-Ranges:bytes
可以處理范圍請求 -
Accept-Ranges:none
不可以處理范圍請求
-
-
Age
- 可以告知客戶端,源服務(wù)器多久之前創(chuàng)建了資源,單位是秒
- 若創(chuàng)建該響應(yīng)的是緩存服務(wù)器,則Age值是指緩存后的響應(yīng)再次發(fā)起發(fā)起認證到認證完成的時間值。代理創(chuàng)建響應(yīng)時必須加上首部字段Age
-
ETag
它是一種可將資源以字符串形式做唯一標(biāo)識的方式,服務(wù)器會為每份資源分配對應(yīng)的
ETag
值,資源被更新時,ETag
值也會被更新,并沒有統(tǒng)一的算法規(guī)則,而是由服務(wù)器來分配- 強
ETag
:無論實體發(fā)生多么細微的變化都會改變其值 - 弱
ETag
:只用于提示資源是否相同,只有資源發(fā)生了根本的改變才會改變ETag值,這時會在字段值最開始加W/
,
ETag:W/"XXX"
- 強
-
Location
- 使用該響應(yīng)字段可以將響應(yīng)接收方引導(dǎo)至某個與請求的URI位置不同的資源
- 基本上,該字段配合3XX,Redirection的響應(yīng),提供重定向的URI
-
Vary
首部字段vary可對緩存進行控制,源服務(wù)器會向代理服務(wù)器傳達關(guān)于本地緩存使用方法的命令
- 當(dāng)代理服務(wù)器接收到服務(wù)器返回包含Vary指定項的響應(yīng)后,僅對請求中含有相同Vary指定首部字段的請求返回緩存
- 即使對相同資源發(fā)起請求,但是由于Vary指定的首部字段不相同,因此必須從源服務(wù)器重新獲取資源
- 例如下面這個,如果使用的
Accept-Language:en-us
字段的值相同,那么直接從緩存返回響應(yīng),否則從源服務(wù)器請求資源后再返回響應(yīng)
image
實體報文首部 (共10種)
首部字段名 | 解釋 |
---|---|
1.Allow | 資源可支持的HTTP方法 |
2.Content-Encoding | 實體主體適用的編碼方式 |
3.Content-Language | 實體主體的自然語言 |
4.Content-Length | 實體主體的大小(單位:字節(jié)) |
5.Content-Location | 代替對應(yīng)資源的URI |
6. Content-MD5 | 實體主體的報文摘要 |
7. Content-Range | 實體主體的位置范圍 |
8. Content-Type | 實體主體的媒體類型 |
9.Expires | 實體主體過期的日期時間 |
10.Last-Modified | 資源的最后修改日期時間 |
其他字段(cookie等)
- cookie,我們下面單獨講這個
cookie
- 注 : 文中例子中的各種請求,報文,均來自 京東物流官網(wǎng)
- ps:小杰個人挺喜歡JDL的標(biāo)語的,有速度,更有溫度,祝JDL越來越好!
set-cookie
屬性 | 解釋 |
---|---|
NAME=VALUE | 賦予Cookie的名稱和其值(必需項) |
expires = DATE | Cookie的有效期(若不指定則默認為瀏覽器關(guān)閉為止) |
path=PATH | 將服務(wù)器上的文件目錄作為Cookie的適用對象(若不指定則默認為文檔所在的文件目錄) |
domin=域名 | 作為Cookie適用對象的域名(若不指定則默認為創(chuàng)建Cookie的服務(wù)器域名) |
Secure | 僅在HTTPS安全通信時才會發(fā)送Cookie |
HttpOnly | 加以限制,使Cookie不能被JS腳本訪問,主要目的是為了防止跨站腳本攻擊(Cross Site Scripting,XSS)對cookie的竊取 |
谷歌瀏覽器控制臺查看cookie
- cookie中的
thor
和JSESSIONID
這兩個key的后HttpOnly
屬性被打上了√,就表明,此key無法被js腳本訪問,防止跨站腳本攻擊(Cross Site Scripting,XSS)對cookie的竊取
我們來看下再console
控制臺輸入document.cookie
得出的cookie無法找到這兩個key
因為這個屬性JSESSIONID
比較重要,存儲的是sessionId,這個要是被別人拿到的話,別人就可以冒充我在網(wǎng)站上做某些事情了,像我自己一樣請求某些數(shù)據(jù)了
postman 模擬拿到cookie后發(fā)送請求
我把網(wǎng)頁上的cookie拿下來,放到postman里測試,發(fā)現(xiàn)和我自己在網(wǎng)站上請求數(shù)據(jù)是一樣的
cookie存儲的地方,清理緩存到底是清理什么?
清理緩存主要就是清理cookie,抹去自己登陸痕跡以及瀏覽器中的資源緩存,重新請求網(wǎng)站資源
HTTP 與 HTTPS
HTTP不足
- 通信使用明文(不加密),內(nèi)容可能會被篡改
- 不驗證通信方的身份,因此有可能遭遇偽裝
- 無法證明報文的完整性,所以有可能已遭遇篡改
HTTPS結(jié)構(gòu)
HTTPS是身披SSL(Secure Socket Layer)外殼的HTTP
- 在采用SSL后,HTP就擁有了HTTPS的加密、證書和完整性保護這些功能
- 想要了解HTTPS是怎么加密的,得先了解下下面兩種提到的加密技術(shù)
對稱加密原理
- 客戶端和服務(wù)端約定好用同一把密鑰
- 這把密鑰可以對數(shù)據(jù)進行加密/解密
- 客戶端和服務(wù)端之間的共享密鑰的傳送問題也是一個問題,如果能夠安全傳送不被截獲的話,那豈不是數(shù)據(jù)也可以安全的傳送到不被截獲?雞生蛋蛋生雞的問題。
- 圖中客戶端和服務(wù)端傳輸加密數(shù)據(jù)的時候,如果雙方的共享密鑰泄露的被黑客截取到的話,黑客就可以用它來解開這加密的數(shù)據(jù),所以對稱加密不安全
非對稱加密原理(公開密鑰加密)
- 一共有兩把密鑰(是一對),一個公開密鑰,一個私人密鑰
- 公開密鑰加密的數(shù)據(jù),只有對應(yīng)的私鑰才可以解密,
- 私鑰加密的數(shù)據(jù),公鑰也可以解密
- 問題就是,從服務(wù)端發(fā)送給客戶端數(shù)據(jù)時無法保證數(shù)據(jù)的安全性,因為此時有可能黑客截獲到了公鑰,對私鑰加密的數(shù)據(jù)進行了解密
- 服務(wù)器端為什么不發(fā)送用公鑰加密的數(shù)據(jù)?因為客戶端沒有私鑰,無法解密。
混合加密原理
聰明的大佬們用兩種加密算法混合了一下
- 客戶端一開始向服務(wù)端傳輸?shù)氖牵霉_密鑰加密的共享密鑰!
- 這樣的話,服務(wù)端收到這個加密的數(shù)據(jù)后用自己的私鑰密鑰解密后得到的就是共享密鑰,以后和客戶端交互時都用這個共享密鑰就可以啦,因為黑客是無法獲得這個共享密鑰的,畢竟公開密鑰加密的數(shù)據(jù),只有對應(yīng)的私鑰才可以解密,而這個私鑰一開始就在服務(wù)端手里而不在黑客手里
我曾經(jīng)以為這樣就萬無一失了,文章也就到此結(jié)束了,可以和血包殺手愉快的timi了,可是,你有沒有聽說過,中間人攻擊?
中間人攻擊
黑客攔截”用公開加密密鑰機密后的共享密鑰“后不是解密不了嗎,好,那我就不攔截這個了,我攔截第一個請求好吧,我攔截服務(wù)端傳給你的公開密鑰,我攔截到了,我再給你個假的,(像極了《讓子彈飛》中,張麻子與馬邦德的關(guān)系,出任鵝城縣長)。從根上就偽裝成你,以后就等于我是個中間人(中轉(zhuǎn)站),所有的請求,數(shù)據(jù)都要經(jīng)過我,那我就可以記錄下來其中你的敏感數(shù)據(jù),可怕。
- 其實中間人攻擊還要有好多種,以后有機會寫一寫,我們先大概了解下是什么意思就好~
數(shù)字證書
- 所以現(xiàn)在問題又到了這里,我無法確保這個公鑰是服務(wù)端發(fā)給我的,還是中間人發(fā)給我的?可這世上沒有用錢解決不了的問題,雖然我確保不了,可是有人可以確保,就是得花錢,我們可以使用由數(shù)字證書認證機構(gòu)(CA)和其他相關(guān)機構(gòu)頒發(fā)的公開密鑰證書
- 數(shù)字證書認證機構(gòu)處于客戶端和服務(wù)器雙方都信賴的第三方機構(gòu)的立場上。有興趣的同學(xué)可以自行去了解下~
- 所以HTTPS靠非對稱性加密及數(shù)字證書保證了安全性
寫在最后
總結(jié)
- 此文章從HTTP報文結(jié)構(gòu)開始,到HTTP首部,到返回狀態(tài)碼,到cookie,再延伸到HTTPS加密方式,每一部分都進行了詳細的介紹,希望對大家有用!
絮絮叨叨
- 如果大家覺得這篇文章對自己有一點點幫助的話,歡迎關(guān)注此號 java小杰要加油
- 原創(chuàng)不易,實需鼓勵
若文章有誤歡迎指出,靚仔靚女們,我們下篇文章見,關(guān)注我,開啟我們的故事