因爲最新的http2,並無被各大瀏覽器普遍使用,因此本文是基於http/1.1所編寫的。
同時通過檢測咱們也發現,chrome等瀏覽器也正是使用http/1.1版本的。html
關於http/1.1協議的詳情,可查看官方文檔web
咱們打開chrome的network,點擊任何一條request請求,便可發現,每一個http headers都包含如下部分:Genaral,Request Headers,Response Headers,Request Payload。算法
General(不屬於headers,只用於收集請求url和響應的status等信息)chrome
Request Headers(請求headers)後端
Response Headers(響應headers)跨域
Request Payload(請求參數)瀏覽器
在http heanders中,爲了方便,分爲如下幾類:Genaral headers(和上面說的General不一樣,這個只是爲了方便統計),Request Headers,Response Headers,Entity Headers(也是爲了方便統計)。緩存
因此,一個完整的請求頭/響應頭,應該除了自身,還包括 General Headers和Entity Headers。安全
一、Genaral headers: 同時適用於請求和響應消息,但與最終消息傳輸的數據無關的消息頭。
二、Request Headers: 包含更多有關要獲取的資源或客戶端自己信息的消息頭。
三、Response Headers:包含有關響應的補充信息,如其位置或服務器自己(名稱和版本等)的消息頭。
四、Entity Headers:包含有關實體主體的更多信息,好比主體長(Content-Length)度或其MIME類型。
Cache-Control——控制緩存的行爲; 詳情
Connection——決定當前的事務完成後,是否會關閉網絡鏈接; 詳情
Date——建立報文的日期時間; 詳情
Keep-Alive——用來設置超時時長和最大請求數; 詳情
Via——代理服務器的相關信息; 詳情
Warning——錯誤通知; 詳情
Trailer——容許發送方在分塊發送的消息後面添加額外的元信息; 詳情
Transfer-Encoding——指定報文主體的傳輸編碼方式; 詳情
Upgrade——升級爲其餘協議;
Accept——客戶端能夠處理的內容類型; 詳情
Accept-Charset——客戶端能夠處理的字符集類型; 詳情
Accept-Encoding——客戶端可以理解的內容編碼方式; 詳情
Accept-Language——客戶端能夠理解的天然語言; 詳情
Authorization——Web 認證信息; 詳情
Cookie——經過Set-Cookie設置的值; 詳情
DNT——代表用戶對於網站追蹤的偏好; 詳情
From——用戶的電子郵箱地址; 詳情
Host——請求資源所在服務器; 詳情
If-Match——比較實體標記(ETag); 詳情
If-Modified-Since——比較資源的更新時間; 詳情
If-None-Match——比較實體標記(與 If-Match 相反); 詳情
If-Range——資源未更新時發送實體 Byte 的範圍請求; 詳情
If-Unmodified-Since——比較資源的更新時間(與 If-Modified-Since 相反); 詳情
Origin——代表了請求來自於哪一個站點; 詳情
Proxy-Authorization——代理服務器要求客戶端的認證信息; 詳情
Range——實體的字節範圍請求; 詳情
Referer——對請求中 URI 的原始獲取方; 詳情
TE——指定用戶代理但願使用的傳輸編碼類型; 詳情
Upgrade-Insecure-Requests——表示客戶端優先選擇加密及帶有身份驗證的響應; 詳情
User-Agent——瀏覽器信息; 詳情
Accept-Ranges——是否接受字節範圍請求; 詳情
Age——消息對象在緩存代理中存貯的時長,以秒爲單位; 詳情
Clear-Site-Data——表示清除當前請求網站有關的瀏覽器數據(cookie,存儲,緩存); 詳情
Content-Security-Policy——容許站點管理者在指定的頁面控制用戶代理的資源; 詳情
Content-Security-Policy-Report-Only—— 詳情
ETag——資源的匹配信息; 連接描述
Location——令客戶端重定向至指定 URI; 詳情
Proxy-Authenticate——代理服務器對客戶端的認證信息; 詳情
Public-Key-Pins——包含該Web 服務器用來進行加密的 public key (公鑰)信息; 詳情
Public-Key-Pins-Report-Only——設置在公鑰固定不匹配時,發送錯誤信息到report-uri; 詳情
Referrer-Policy——用來監管哪些訪問來源信息——會在 Referer 中發送; 詳情
Server——HTTP 服務器的安裝信息; 詳情
Set-Cookie——服務器端向客戶端發送 cookie; 詳情
Strict-Transport-Security——它告訴瀏覽器只能經過HTTPS訪問當前資源; 詳情
Timing-Allow-Origin——用於指定特定站點,以容許其訪問Resource Timing API提供的相關信息; 詳情
Tk——顯示了對相應請求的跟蹤狀況; 詳情
Vary——服務器緩存的管理信息; 詳情
WWW-Authenticate——定義了使用何種驗證方式去獲取對資源的鏈接; 詳情
X-XSS-Protection——當檢測到跨站腳本攻擊 (XSS)時,瀏覽器將中止加載頁面; 詳情
Allow——客戶端能夠處理的內容類型,這種內容類型用MIME類型來表示; 詳情
Content-Encoding——用於對特定媒體類型的數據進行壓縮; 詳情
Content-Language——訪問者但願採用的語言或語言組合; 詳情
Content-Length——發送給接收方的消息主體的大小; 詳情
Content-Location——替代對應資源的 URI; 詳情
Content-Range——實體主體的位置範圍; 詳情
Content-Type——告訴客戶端實際返回的內容的內容類型; 詳情
Expires——包含日期/時間, 即在此時候以後,響應過時; 詳情
Last-Modified——資源的最後修改日期時間; 詳情
HTTP 協議是無狀態的,主要是爲了讓 HTTP 協議儘量簡單,使得它可以處理大量事務。HTTP/1.1 引入 Cookie 來保存狀態信息。服務器
Cookie 是服務器發送到用戶瀏覽器並保存在本地的一小塊數據,它會在瀏覽器以後向同一服務器再次發起請求時自動被攜帶上,用於告知服務端兩個請求是否來自同一瀏覽器。因爲以後每次請求都會須要攜帶 Cookie 數據,所以會帶來額外的性能開銷(尤爲是在移動環境下)。
Cookie 曾一度用於客戶端數據的存儲,由於當時並無其它合適的存儲辦法而做爲惟一的存儲手段,但如今隨着現代瀏覽器開始支持各類各樣的存儲方式,Cookie 漸漸被淘汰。新的瀏覽器 API 已經容許開發者直接將數據存儲到本地,如使用 Web storage API(本地存儲和會話存儲)或 IndexedDB。
服務器發送的響應報文包含Set-Cookie首部字段,客戶端獲得響應報文後把 Cookie 內容保存到瀏覽器中。
HTTP/1.1 200 OK Content-type: text/html Set-Cookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7
客戶端以後對同一個服務器發送請求時,會從瀏覽器中取出 Cookie 信息並經過 Cookie 請求首部字段發送給服務器。
GET /sample_page.html HTTP/1.1 Host: www.example.org Cookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7
會話期 Cookie:瀏覽器關閉以後它會被自動刪除,也就是說它僅在會話期內有效。
持久性 Cookie:指定一個特定的過時時間(Expires)或有效期(max-age)以後就成爲了持久性的 Cookie。
安全 Cookie:指定HttpOnly,這樣cookie不能使用 JavaScript 經由 Document.cookie 屬性,來防範跨站腳本攻擊(XSS)。
HTTPS Cookie: 指定Secure,只有在請求使用SSL和HTTPS協議的時候纔會被髮送到服務器。
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;HttpOnly Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;Secure
下降客戶端獲取資源的延遲:緩存一般位於內存中,讀取緩存的速度更快。而且緩存在地理位置上也有可能比源服務器來得近,例如瀏覽器緩存(可是隻能緩存get,不能緩存其餘類型請求)。
cache FAQ MDN
流程圖:
max-age值爲緩存的毫秒數。
能夠看到response-headers中設置了cache-control,並大於0,則下次直接從緩存(from disk cache)中獲取
當發現Cache-Control設置的毫秒數過時了,則直接發送請求:
——若是響應中包含Etag(服務器生成的值),則瀏覽器再次向web服務器發送請求並帶上頭If-None-Match(Etag的值),web服務器收到請求後發現有頭If-None-Match 則與被請求資源的相應校驗串進行比對,決定返回200或304(瀏覽器會從緩存中獲取)。
——若是響應中不包含Etag,則進行Last-Modified判斷
當發現response header中含有Last-Modified,則再次向web服務器請求時帶上頭 If-Modified-Since,web服務器收到請求後發現有頭If-Modified-Since 則與被請求資源的最後修改時間進行比對,而後服務器決定返回200或者304(緩存)
瀏覽器強制告訴服務器不緩存資源:
//request headers Cache-Control:max-age=0, no-cache
瀏覽器一般使用MIME類型(而不是文件擴展名)來肯定如何處理文檔;所以設置正確的MIME類型附加到headers是很是重要的。
除了上面的基本的5中類型外,還有一種類型,即multipart類型。
multipart/form-data 在表單中經過post上傳
multipart/byteranges (不經常使用,不知道)
通常的,若是沒有顯示的在request headers的Allow上設置類型,瀏覽器的MIME 嗅探會推測出來對應的類型,若是發現找不到特定的子類型,則給出默認類型,好比對於text文件類型若沒有特定的subtype,就使用 text/plain。相似的,二進制文件沒有特定或已知的 subtype,即便用 application/octet-stream。
一、BASIC 認證(基本認證)
二、DIGEST 認證(摘要認證)
三、SSL 客戶端認證
四、FormBase 認證(基於表單認證)
當在瀏覽器端輸入一個url時,會自動彈出一個框,要求輸入用戶名和密碼。此種方式爲basic認證。
下面是認證執行過程:
第一步:在瀏覽器地址欄中輸入 http://localhost:8080/auth
第二步: 服務器執行,發現須要認證,返回這個請求的響應。並在response headers中添加WWW-Authenticate,將http請求狀態設置爲401.
瀏覽器檢測到WWW-Authenticate爲basic後,自動彈出框。
第三步: 當用戶看到框後,輸入 用戶名和密碼,瀏覽器會將用戶名和密碼經過base64方式編碼,而後添加到 request headers的 Authorization 中發送給服務器,瀏覽器驗證經過,返回200狀態碼
若是驗證不經過,則繼續返回狀態碼401,提示驗證失敗。
缺點:
BASIC 認證雖然採用 Base64 編碼方式,但這不是加密處理。不須要任何附加信息便可對其解碼。換言之,因爲明文解碼後就是用戶 ID和密碼,在 HTTP 等非加密通訊的線路上進行 BASIC 認證的過程當中,若是被人竊聽,被盜的可能性極高。
爲了彌補Basic認證沒有加密所帶來的不安全性,出現了DIGEST 認證。
過程以下:
第一步:在瀏覽器地址欄中輸入 http://localhost:8080/auth
第二步: 服務器執行,發現須要認證,返回這個請求的響應。並在response headers中添加WWW-Authenticate(包含有隨機碼nonce),將http請求狀態設置爲401.
瀏覽器檢測到WWW-Authenticate爲 digest 後,自動彈出框。
第三步: 當用戶看到框後,輸入 用戶名和密碼,瀏覽器會將用戶名和上步返回的nouce,添加到 request headers的 Authorization 中,同時也將通過 MD5 運算後的密碼字符串,生成key爲response,一併添加到Authorization 中。至此請求的request headers的Authorization 包含有以下信息。
//request header Authorization: Digest username="my name",realm="DIGEST",nounce="xxxxxxxxxxx",algorithm="MD5",response="xxxxxxxxxxxxx"
而後發送給服務器,瀏覽器驗證經過,返回200狀態碼。
若是驗證不經過,則繼續返回狀態碼401,提示驗證失敗。
缺點: 雖然 DIGEST 認證提供了高於 BASIC 認證的安全等級, DIGEST 認證提供防止密碼被竊聽的保護機制,但並不存在防止用戶假裝的保護機制,仍達不到多數 Web 網站對高度安全等級的追求標準。
對於 BASIC 認證和 DIGEST 認證來講,只要輸入的用戶名和密碼正確,便可認證是本人的行爲。但若是用戶名和密碼被盜,就頗有可能被第三者冒充。
而利用 SSL客戶端認證則能夠避免該狀況的發生。在SSL認證時,必須使用https協議。
因爲SSL中的各類加密和祕鑰算法過於複雜,有興趣的能夠直接閱讀SSL相關書籍,本文忽略詳細過程。
基於表單認證的標準規範還沒有有定論,通常會使用 Cookie 來管理。
認證過程:
第一步:當用戶在瀏覽器的登陸頁面,輸入用戶名和密碼,經過http請求發送給後端。
第二步:後端保存用戶的信息到session中,並返回sessionId, 經過http添加到response headers的Set-cookie中
//response headers Set-cookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7
而後瀏覽器成功登陸,並跳轉頁面。
第三步:當用戶訪問我的中心或者其餘頁面時。http請求的request header中會自動攜帶cookie
//request headers Cookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7
這樣,服務端會認爲是你本人在操做。
可是若是攻擊者經過「跨站腳本攻擊(XSS)」,經過docuemnt.cookie來獲取cookie,則sessionID很容易被盜。
爲減輕XSS形成的損失,能夠事先在 Set-cookie內加上 httponly 屬性,這樣就禁止了docuemnt.cookie操做。
Set-cookie: PHPSESSID=kq8v6iujarsgflkeq7shmai9c7, httponly
是一種機制,它使用額外的 HTTP 頭來告訴瀏覽器 讓運行在一個 origin (domain) 上的Web應用被准許訪問來自不一樣源服務器上的指定的資源。當一個資源從與該資源自己所在的服務器不一樣的域、協議或端口請求一個資源時,資源會發起一個跨域 HTTP 請求。
須要知足下列 全部條件:
第一條: 請求方式必須爲 GET | HEAD | POST
第二條: Content-Type 的值必須屬於下列之一:application/x-www-form-urlencoded | multipart/form-data | text/plain
第三條: 在請求中,不會發送自定義的頭部(如X-Modified)
例如: 在http://foo.exmaple上要訪問 http://bar.other上的資源。則
//request headers上添加 Origin: http://foo.example
//response headers返回 Access-Control-Allow-Origin: *
因爲在 http://foo.example 上要訪問 http://bar.other,因此http://bar.other必需要告訴其...,能不能訪問我。*號表示該資源能夠被任意外域訪問。
若是返回
Access-Control-Allow-Origin: http://foo.example
表示,http://bar.other的資源只能被http://foo.example訪問,其餘網站不能訪問我。
知足下列條件 之一:
第一條: http請求方式爲下列:PUT | DELETE | CONNECT | OPTIONS | TRACE | PATCH
第二條: Content-Type 的值不屬於下列之一: application/x-www-form-urlencoded | multipart/form-data | text/plain
第三條: 在請求中,發送自定義的頭部(如X-Modified)
若是在 http://foo.exmaple 上要訪問 http://bar.other/resources/po... 上的資源。且 request headers 中 Content-Type爲application/xml,請求method爲post。
那麼此請求是個「非簡單請求」。首先瀏覽器會自動發送帶有options選項的預檢請求,而後發送實際請求
//預檢請求request headers OPTIONS /resources/post-here/ HTTP/1.1(自動,不須要設置) Access-Control-Request-Method: POST Access-Control-Request-Headers: Content-Type
//預檢請求返回response headers Access-Control-Allow-Origin: * Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400
Access-Control-Allow-Origin 代表服務器容許任何其餘服務器訪問本身。
Access-Control-Allow-Methods 代表服務器容許客戶端使用 POST, GET, OPTIONS 方法發起請求。
Access-Control-Allow-Headers 代表服務器容許請求中攜帶字段 X-PINGOTHER, Content-Type。
Access-Control-Max-Age 代表在86400內,不會再發送預檢請求。
而後瀏覽器接着發送實際請求
POST /resources/post-here/ HTTP/1.1 Content-Type: application/xml; charset=UTF-8
實際請求返回
HTTP/1.1 200 OK Access-Control-Allow-Origin: *
通常而言,對於跨域 XMLHttpRequest 或 Fetch 請求,瀏覽器不會發送身份憑證信息。若是要發送憑證信息,須要設置 XMLHttpRequest 的某個特殊標誌位。
var xhr = new XMLHttpRequest(); var url = 'http://xxxxxxxxx'; xhr.open('GET', url, true); xhr.withCredentials = true; // 設置發送人請求時 攜帶 cookie憑證 xhr.send();
請求發送
GET /resources/access-control-with-credentials/ HTTP/1.1 Cookie: pageAccess=2
請求返回
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://foo.example //在攜帶憑證的請求中,返回不得設置爲*, 必須設置爲具體域名 Access-Control-Allow-Credentials: true //必須攜帶這個,不然響應內容不會返回給請求的發起者
4.1 Access-Control-Allow-Origin
它的值只有兩種,要麼*, 好麼具體的域名 <origin>
4.2 Access-Control-Expose-Headers
在跨域訪問時,XMLHttpRequest對象的getResponseHeader()方法只能拿到一些最基本的響應頭:
Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma
沒法訪問其餘的響應頭(甚至在控制檯network中看不到),如 set-cookie等,若是要訪問其餘頭,則須要服務器設置,將能返回的響應頭放入白名單
Access-Control-Expose-Headers: set-cookie
這樣瀏覽器就可以經過getResponseHeader訪問set-cookie響應頭了
4.3 Access-Control-Max-Age
指定了預檢請求的結果可以被緩存多久,在此時間內,不會再發起預檢請求。
Access-Control-Max-Age: <seconds>
4.4 Access-Control-Allow-Credentials指定了當瀏覽器的credentials設置爲true時,是否容許瀏覽器讀取response的內容。