黃金周花了5天時間讀完了上野宣的《今夜わかるHTTP》(圖解HTTP),對HTTP協議進行了一次掃盲,整體而言書寫的非常淺顯易懂,是本掃盲向的書,我一個準備轉行的門外漢也能很輕鬆地看懂。對於進階學習者還是去啃TCP/IP卷吧。在這共享下我的學習筆記,也方便自己將來查缺補漏。

提醒:本筆記記錄得比較粗暴適合讀完原書過來自檢複習的人羣

## 網路基礎TCP/IP 協議

1. TCP/IP協議簇自上而下分為4層:應用層,傳輸層,網路層,數據鏈路層

* 應用層:決定向用戶提供應用服務時的通信活動,HTTP(Hypertext Transfer Protocol),FTP(File Transfer Protocol),DNS(Domain Name System)均在這層;

* 傳輸層:提供處於網路連接中的兩臺計算機之間的數據傳輸,TCP(Transmission Control Protocol),UDP(User Data Protocol)

* 網路層:規定以怎樣的路徑到達目標計算機,並把數據包傳輸給對方,IP(Internet Protocol)

* 鏈路層:鏈接網路的硬體部分,操作系統,硬體驅動,網卡,光纖

2. 協議的數據流:發送端自應用層到鏈路層,接收端自鏈路層到應用層。客戶端在應用層發出HTTP,傳輸層TCP協議對HTTP協議進行分割打上標記和埠號,網路層IP協議增加通信目的地的MAC(Media Access Control Address)地址,發給鏈路層完成通信請求;接收端伺服器在鏈路層接受數據,往上層發送。

3. IP協議:把數據包傳送給對方,兩個重要條件:IP地址(節點被分配的地址)和MAC地址(網卡所屬的固定地址)。通過ARP(Address Resolution Protocol)請求完成解析MAC地址(ARP單播於ARP廣播)。(參考連接:[為什麼需要MAC地址?](有了 IP 地址,為什麼還要用 MAC 地址?),[什麼是ARP協議?](拼客學院陳鑫傑:圖解ARP協議(一)) )

4. 路由選擇(routing):沒有人能夠全面掌握互聯網中的傳輸狀況,需要在多次中轉才能到達目的地,這種中轉為路由。

5. TCP協議:作用於傳輸層,使用位元組流服務(Byte Stream Service)將大數據切割成segment為單位的數據包;使用三次握手策略(Three-way Handshaking)SYN - SYN/ACK - ACK傳送數據包,四次揮手 FIN - ACK - FIN - ACK 來中斷鏈接。

6. DNS服務:DNS協議提供通過域名查找IP地址,或者逆向IP地址查找域名的服務。

7. URI與URL:URI(Uniform Resource Identifier)與URL(Uniform Resource Locater),URL是URI的子集,也可以說URL是URI的實現。好比名字,身份證號,學號都是一個人的URI,每條單獨拿出來就是一個URL(URI與URL的區別)。

## 簡單的HTTP協議

1. 一個HTTP通信中必定存在一對客戶端與服務端,HTTP協議規定請求從客戶端發出,由服務端相應並返回。

2. 請求報文由請求方法,請求URI,協議版本,可選請求首部欄位,和內容實體構成。

3. 響應報文由協議版本,狀態碼,原因短語,可選的首部響應欄位以及響應實體構成。

4. HTTP是一種無狀態(stateless)協議。協議對於發送過的請求或響應不做持久化處理。因此發展了Cookie技術用來保存用戶態。

5. HTTP請求中指定URI的方式有很多,可以放在請求URI中,也可以將URI中的域名或者IP放在可選首部欄位中,也可以用一個*代替URI表示對伺服器本體發起請求。

6. HTTP請求方法

* GET:獲取URI指定的資源。如果資源為文本直接返回,如果是CGI(Common Gateway Interface)那樣的程序則返回執行後結果。

* POST:傳輸實體的主體。POST的目的不在於獲取響應的主體內容。比如發送數據給CGI處理獲取返回結果。

* PUT方法:傳輸文件到指定URI位置。不帶驗證機制,任何人均可上傳存在安全問題,一般web禁止。若干附帶嚴重或者採用REST(RE presentational State Transfer 表徵狀態轉移)標準的網站可能會開放PUT。

* HEAD方法:與GET相似,但不獲取報文主體,僅用來確認URI有效性以及資源更新日期。

* DELETE方法:刪除URI指定的文件,與PUT相反

* OPTIONS方法:詢問支持的方法,例如:OPTIONS * HTTP/1.1 HOST:hackr.jp 來獲取HOST指定伺服器支持的方法。

* TRACE方法:追蹤路徑(請求在中轉被篡改的記錄)。讓伺服器將之前的通信環返回給客戶端。不常用,且容易引發XST(Cross-Site Tracing)攻擊。

* CONNECT:要求用隧道協議連接代理。與代理伺服器通信時建立隧道,實現用隧道協議進行TCP通信,建立成功後通過隧道訪問目標伺服器。主要用SSL(Secure Sockets Layer)和TLS(Transport Layer Security)協議將內容加密後通過隧道傳輸。

7. 通過持久連接節省通信量。

* 背景:之前傳輸文本小:TCP三次握手 - HTTP請求與響應 - TCP四次揮手,現在網站內容量大(例如多圖片網站)每次請求都會造成TCP連接建立與斷開增加通信量消耗

* 持久化連接(HTTP Persistent Connections,HTTP keep-alive或HTTP connection reuse),只要任何一端沒有明確提出斷開連接則保持TCP連接。減少TCP連接和斷開的負載,使得HTTP請求能夠更快完成

* 管線化(pipelining):持久化連接保證了發送請求後無需等待響應也可以直接發送下一個請求,發送請求由串列變成並行

8. Cookie狀態管理

* HTTP的無狀態性減少了伺服器CPU及內存資源的消耗

* Cookie技術:通過在請求和響應報文中寫Cookie信息來控制客戶端狀態(比如,登陸態)

* 客戶端發送請求 -> 伺服器響應,首部欄位包含set-Cookie -> 客戶端發送請求,首部欄位包含cookie -> 服務端解析cookie認識客戶端並從之前服務記錄中獲得客戶端狀態信息。

## HTTP報文內的HTTP信息

1. HTTP報文分為請求報文與響應報文,內容為:報文首部以及報文主體組成,兩者由CR+LF(Carriage Return 回車符0x0d 和Line Feed 換行符0x0a)隔開。

2. 請求報文

* 請求行:請求的方法,URI,和HTTP版本,比如:GET / HTTP/1.1

* 首部欄位:通用首部,請求首部,實體首部,Cookie

3. 響應報文

* 響應行:響應的狀態碼,原因短語和HTTP版本,比如:HTTP/1.1 200 OK

* 首部欄位:通用首部,響應首部,實體首部,Cookie

4. 編碼提升傳輸速率

* 報文(Message)和實體(entity)。報文是HTTP通信的基本單位,由8位位元組流(octet sequence)組成,通過HTTP傳輸;實體是響應或者請求的有效載荷,由實體首部和實體主體組成。

* HTTP報文的主體用來傳輸請求或響應的實體主體,通常報文主體=實體主體,但為提升傳輸效率,編碼操作後兩者不同。好比我們發郵件增加了超大附件,傳輸時用ZIP壓縮一樣,壓縮文件與原附近不同。

* 內容編碼:應用在實體上的編碼格式,保持實體信息,客戶端接受並解碼。常用編碼:GUN gzip,UNIX compress,zlib deflate,identity(不編碼)。對應首部欄位:Content-Encoding。

* 分塊傳輸編碼(Chunked Transfer Coding):把實體數據分割成多塊,能讓瀏覽器逐步顯示頁面,不至於數據傳輸沒完成就無法顯示頁面。每塊用一個**十六進位數**標記塊大小,最後一塊用**「0(CR+LF)」**標記。對應首部欄位:Transfer-Encoding。

* 發送多數據對象集合:HTTP發送的一份報文主體內可包含多類型實體(圖片,視頻等等)。包括:multipart/from-data(表單上傳),multipart/byteranges(多範圍內容)使用「--boundary字元串」來進行分割,響應報文中包含多個範圍的內容時使用**狀態碼206** Partial Content。在報文中使用多部分對象集合時需要在首部加上欄位Content-type。

* 範圍請求(Range Request):使用首部欄位Range指定資源的byte範圍,如,Range:bytes=5001-10000; Range:bytes=-3000, 5000-;對於多範圍請求。響應碼為206 Partial Content,響應報文首部欄位包含Content-type: multipart/byteranges。如果無法響應則會返回200 OK和完整的內容。應用在:下載的斷點續傳等。

* 內容協商:客戶端與服務端就響應的資源進行交涉,然後給客戶端提供最合適的資源。比如中文版本的瀏覽器訪問google會返回中文版本的google主頁

- 交涉點包括:語言,字符集,編碼方式等等。請求的首部欄位中包含:Accept,Accept-Charset,Accept-Encoding,Accept-Language,Content-Language;

- 內容協商技術:伺服器驅動協商(Server-driven Negotiation)(伺服器參考請求欄位來判斷響應內容),客戶端驅動協商(Agent-driven Negotiation)用戶手動切換,透明協商(Transparent Negotiation)兩者結合。

## HTTP響應狀態碼

1. 狀態碼:3位數字+原因短語,如200 OK。主要有5種:1XX = informational 接受信息正在處理;2XX = Success 請求正常處理完畢;3XX = Redirection 需要附加操作以完成請求;4XX = Client Error 無法處理請求;5XX = Server Error 伺服器處理請求出錯。

2. 2XX系列:處理成功系列

* 200 OK:正常處理(GET,HEAD請求的響應報文不同,後者無實體)

* 204 No Cotent:處理成功,但無相關內容,返回報文中不含實體,瀏覽器得到204後不會刷新頁面。一般用於客戶端往服務端發信息,但服務端無需返回時使用。

* 206 Partial Content:對應Range Request,包含由Content-Range指定的實體

3. 3XX系列:瀏覽器需要執行某些特殊處理以正確處理請求。

* 301 Moved Permanently:永久性重定向,表示訪問的URI資源已經被分配了新的URI,如果之前將該資源保存為書籤,這時就應該安裝Location首部欄位提示的URI**更新書籤**。

* 302 Found:請求的資源被臨時分配了新的URI,希望用戶**本次**使用新的URI,也就是說將來URI還會改變,如果保存了書籤,這時瀏覽器不會去像301那樣去更新書籤。

* 303 See Other:請求對應的資源存在另外一個URI,應該使用**GET方法**定向獲取該資源,不像302,303明確要求用戶用GET。比如用POST訪問Server CGI,Server把處理結果放在某個URI下,返回303通知用戶用GET去取,這就是303絕佳應用場景。

* 實際上,301,302,303出現時,幾乎所有的瀏覽器都會把POST改成GET並刪除報文主體,然後再次發送;但301,302標準是禁止POST轉GET的

* 304 Not Modified 客戶端發送附帶條件請求時,若未滿足條件返回304,且不包含響應主體,與重定向無關。(附帶條件請求:首部包含If—Match,If-None-Match,If-Modified—Since,If-Range,If-Unmodified-Since等欄位之一的請求)

* 307 Temporary Redirect:與302相同,但307根據標準不會把POST改成GET,但視情況而定。

4. 4XX系列:客戶端錯誤

* 400 Bad Request:請求報文出現語法錯誤,瀏覽器會像200 OK那樣對待400.

* 401 Unauthorized:第一次返回,響應報文中會包含WWW-Authenticate首部詢問用戶信息,通知用戶進行HTTP認證(BASIC,DIGEST認證)同時瀏覽器會彈出認證對話窗,第二次返回表示認證失敗。

* 403 Forbidden:伺服器拒絕防問請求資源,可能由於許可權原因。可以在響應主體中添加拒絕理由

* 404 Not Found:表示伺服器上無法找到請求的資源

* 405 Method Not Allowed:客戶端請求中使用了伺服器禁用的方法。

5. 5XX系列:伺服器錯誤

* 500 Internal Server Error:伺服器執行出錯,可能是web應用bug導致

* 503 Service Unavailable: 表示伺服器暫時處於超負荷或者停機維護,當前無法處理請求,可以通過RetryAfter欄位通知客戶端重試時間。

## 與HTTP協作的web伺服器

1. Web伺服器可以使用虛擬主機(Virtual Host)搭建多個獨立域名的Web網站,也可以作為通信路徑中的中轉伺服器提升傳輸效率。

2. 同一臺主機上託管了多個域名時,這些域名被DNS解析後均會指向該主機的IP地址,這樣會混淆,因此發送HTTP請求時需要在Host首部內完整指明主機域名。

3. HTTP通信中,除了伺服器和客戶端以外還有其他程序配合伺服器工作:

* 代理:中間人角色,接受客戶端請求並轉發給伺服器,接受伺服器響應並轉發給客戶端;

* 網關:轉發其他伺服器的通信數據,接受客戶請求時像源伺服器一樣對請求進行處理,客戶端都無法察覺;

* 隧道:相隔較遠的客戶端與伺服器兩者之間進行中轉,並保持通信連接的應用程序。

4. 代理:代理不會改變訪問的URI,每次通過代理轉發請求或響應時都會追加Via首部,例如:Via:proxy1,proxy2。使用理由:利用緩存技術減少網路帶寬的流量,訪問控制,獲取訪問日誌。

* 緩存代理(Caching Proxy):緩存資源副本,接到同樣請求時直接返回,反之為非緩存代理;

* 透明代理(Transparent Proxy):不會報文進行任何修改加工的代理,反之為非透明代理。

5. 網關:與代理類似,網關可以把HTTP協議轉換為非HTTP協議,利用網關能提升通信安全,可以在客戶端與網關之間的通信加密。比如:網關連接資料庫使用SQL查詢(非HTTP系統),網關與信用卡結算系統(非HTTP系統)聯動。

6. 隧道:確保客戶端能與伺服器進行安全的通信,隧道不回去解析HTTP請求。

7. 緩存: 代理伺服器或客戶端本地磁碟保存的資源副本。利用緩存可以減少對源伺服器的訪問。

* 緩存伺服器:代理伺服器轉發請求時會保存一份資源副本,下次遇到同樣請求直接返回。

* 緩存時效性:根據緩存有效期,客戶端要求,去更新資源

* 客戶端緩存:緩存在瀏覽器中,請求時之前從本地返回,如果緩存過期則會發送請求去伺服器更新資源。

## HTTP首部

1. HTTP/1.1的4種首部欄位類型:

* 通用首部欄位(General Header Fields):請求和響應報文都會使用的欄位

* 請求首部欄位(Request Header Fields)

* 響應首部欄位(Response Header Fields)

* 實體首部欄位(Entity Header Fields):請求與響應報文的實體部分使用的首部,補充與實體相關的信息,比如更新時間。

2. 非HTTP/1.1的首部欄位:RFC2616規定的47種欄位外的欄位:Cookie,Set-Cookie,Content-Disposition等等

3. 按是否緩存代理的行為劃分為:端到端首部(End to end Header)、逐跳首部(Hop by hop Header)。

* 端到端首部(End-to-End Header):轉發請求/響應對應的最終目標,且必須保存在由緩存生成的響應中;

* 逐跳首部(Hop-by-Hop Header):只對單次轉發有效,會因通過緩存或代理而不再轉發,使用逐跳首部需要提供Connection首部。總共只有8個

4. 通用欄位:

* Cache-Control:控制緩存行為,請求與響應有不同的指令集。

* 是否能緩存:public,private,no-cache

- public:其他用戶也可以利用緩存

- private:指定用戶專用,緩存伺服器只對特定用戶返回緩存,對於其他用戶不返回緩存(緩存用戶個人資料)

- no-cache:要求中間伺服器不返回緩存資源,防止從緩存中返回**過期資源**,緩存會向源伺服器進行有效期確認後處理資源 do not serve from cache without revalidation。請求使用的話表示不接受代理緩存,響應使用的話表示不允許代理緩存。響應中還可以指定no-cache=Location,接收到該參數指定的對應的響應報文後,就不能使用緩存。

* 控制可執行緩存對象的指令:no-store

- no-store:暗示請求或響應中包含機密信息。注意區分no-cache,no-cache表示**不緩存過期資源**,no-store是真正的不緩存。

- max-age:請求中包含max-age時,如果代理的資源緩存時間比max-age小,則直接返回緩存,否則轉發給源伺服器獲取資源。如果設置為0表示需要把請求轉發給源伺服器;響應中包含max-age時表示緩存伺服器不再對緩存有效性進行確認,max-age指定的為最長時間。max-age會覆蓋Expires。

- s-maxage:與max-age相同,不同點是該指令只適合供多用戶使用的公共緩存(代理)伺服器。使用s-maxage的話會忽略Expires和max-age。

- min-fresh:請求中表示要求緩存伺服器返回至少還未過指定時間的緩存資源。比如,指定為60s,那麼超過60sde緩存都無法作為響應。

- max-stale:請求中表示即使過期,只要在指定範圍內則接受。例如Cache-Control: max-stale = 3600,緩存3600s以內的資源無論是否過期都可以作為響應返回。

- only-if-cached:請求中表示緩存伺服器有該緩存時就返回,無論該資源是否有效過期,不去源伺服器確認有效性。若沒有返回504 Gateway Timeout。

- must-revalidate:請求中要求代理向源伺服器確認緩存是否有效,若代理無法連上源伺服器則返回504。must-revalidate會覆蓋max-stale。

- proxy-revalidate:請求中要求緩存伺服器返迴響應之前必須驗證有效性。

- no-transform:無論是請求還是響應緩存都不能改變實體主體的媒體類型,防止緩存或代理壓縮圖片等

- Cache-Control拓展,cache-extension token,僅對理解它的緩存伺服器有效,不理解則被忽略。

* Connection:請求或響應中控制不再發給代理的首部欄位,比如Connection: Upgrade,那麼Upgrade欄位將不會被轉發;管理持久連接,HTTP/1.1默認持久連接,如果伺服器表示希望中斷可以響應Connection:close,HTTP/1.1之前的版本都是默認非持久連接這樣,為達到持久連接,請求中加上Connection:keep-alive,響應中添加Connection:keep-alive Keep-alive:timeout=10, max=500

* Date:HTTP報文生成的日期與時間。

* Pragma:HTTP/1.1之前的歷史遺留,僅為了向後兼容性。唯一形式Pragma:no-cache,與Cache-Control:no-cache並用防止不兼容。

* Trailer:說明在報文主體中記錄了一些首部欄位,該欄位可以用於分塊傳輸編碼。

* Transfer-Encoding:規定傳輸報文主體時採用的編碼方式。對於HTTP/1.1而已僅有分塊傳輸有效。Transfer-Encoding:chunked

* Upgrade:檢查是否可用更好版本協議通信。例如,Upgrade:TLS 1.0 Connection: Upgrade。伺服器可以返回101 Switching Protocols作為響應。

* Via:追蹤客戶端與伺服器之間的請求與響應報文的傳輸路徑,還可以避免請求迴環的發生。Via經常和TRACE一起使用,其中Max-Forwards=0時,代理不在轉發,返回自己到Via中返迴響應。

* Warning:警告碼+警告主機:埠+內容+日期時間。目前有7種。

5. 請求首部欄位

* Accept:通知伺服器客戶能夠處理的媒體類型和優先順序,使用type/subtype指定類型。例如:text/html,image/jpeg,video/mpeg等。可以用q指定權重,默認為1.0(最大),可以精確到小數點後3位,例如:Accept: text/plain; q=0.3, application/zip; q=0.5。

* Accept-Charset:客戶端接受的字符集,q表示權重,例如,Accept-Charset:unicode-1-1;q=0.8。

* Accept-Encoding:客戶端支持的內容編碼,q表示權重,例如,Accept-Encoding:gzip, deflate。

* Accept-Language:客戶端支持的自然語言集,q表示權重。Accept-Language: zh-cn; q=0.9。

* Authorization:告知伺服器用戶的認證信息(證書值)。通常收到401後響應中會包含WWW-Authenticate要求認證,這是用戶返回Authorization欄位包含認證信息再次請求。

* Expect:表期待某特定行為。若伺服器無法回應期待則返回417 Expectation Failed。目前只有100-continue表示希望伺服器對正在等待的客戶端響應100 Continue。

* From:告知伺服器使用用戶代理的電子郵箱地址。為了顯示搜索引擎等用戶代理負責人的聯繫方式。伺服器可以通過這個郵箱聯繫客戶端。

* Host:定位虛擬主機。因為一個IP下可能有多個域名指定的虛擬主機。若伺服器為指定主機名那麼允許為空。該欄位為請求中唯一的必須欄位。

* If-Match: + ETag,告訴伺服器匹配所用的實體標記值ETag,這時伺服器無法使用弱ETag值,當兩值一致時處理請求,否則返回412 Precondition Failed。用「*」表示匹配所有ETag,只要有資源就會處理。

* If-Modified-Since:如果在指定日期之後發生更新,則處理;否則返回304 Not Modified。用於客戶端或代理伺服器向源伺服器詢問本地資源的有效性來更新資源。可以通過Last-Modified來確認資源更新時間。

* If-None-Match:與If-Match相反,可以用在GET和HEAD方法中來更新資源,類似於If-Modified-Since。

* If-Range:If-Range於Range搭配使用,如果資源ETag相匹配,則返回206 Partial Content,否則返回200 OK附帶全部內容。如果不用If-Range使用If-Match將需要消耗2次請求(不匹配返回412,再次發送新請求)。

* If-Unmodified-Since:與If-Modified-Since相反,如果發生更新返回412。

* Max-Forwards:使用TRACE或OPTIONS方法,發送Max-Forwards請求時,每經過一個代理則Max-Forwards減一併轉發,等於0時直接返迴響應。這樣可以用來調差請求失敗的原因,把握傳輸路徑的通信狀況。

* Proxy-Authorization:客戶端與代理伺服器之間的認證質詢。

* Range:發起範圍請求。成功則返回206,失敗返回200。

* Referer:告知伺服器資源請求者的URI。

* TE:客戶端能夠響應的編碼方式和優先順序。與Accept-Encoding很像。可以指定trailer的分塊編碼方式,只需賦值給TE:trailers。

* User-Agent:創建請求的瀏覽器和用戶代理等信息傳給伺服器。爬蟲會加入作者電子郵箱,經過代理也可能會被加上代理伺服器名稱。

6. 響應首部欄位

* Accept-Ranges:告訴客戶端是否接受範圍請求,接受為bytes,不接受為none。

* Age:表示源伺服器多久之前創建了響應。Age值表示的是緩存後的響應再次發起認證到認證完成的時間值。

* ETag:告知客戶端實體標識。伺服器為每份資源分配對應的ETag,當資源更新時ETag也更新,ETag生成無統一演算法規則。如下載中斷在連接時會使用ETag來指定資源。

* 強ETag和弱ETag:強ETag,無論發生多麼細微的變化都會改變,例如,ETag:usagi-123,弱Etag會在資源發生根本改變時才會改變,例如,ETag:W/"usagi-123"。

* Location:引導客戶端,配合3XX重定向提示客戶端資源的所在URI,客戶端收到後重新發起請求。

* Proxy-Authenticate:代理伺服器發送需要的認證信息給客戶端,類似於WWW-Authenticate,不同在於一個是代理,一個是源伺服器。

* Retry-After:與503 Service Unavailable或3XX 一起使用,告知客戶端多久以後來訪問,可以指定具體時間或響應傳建後的秒數。

* Server:告訴服務端當前伺服器應用程序信息,版本號之類的

* Vary:從代理伺服器接受到源伺服器返回包含 Vary 指定項的響應之後,若再要進行緩存,僅對請求中含有相同 Vary 指定首部欄位的請求返回緩存。即使對相同資源發起請求,但由於 Vary 指定的首部欄位不相同,因此必須要從源伺服器重新獲取資源。假如源伺服器返回給代理Vary:Accept-Language,那麼如果請求的Accept-Language相同,直接緩存返回,否則向伺服器重新發起請求。

* WWW-Authenticate:用於HTTP認證,告知客戶端認證方案(Basic還是Digest)和帶參數的提示質詢(challenge),伴隨401返回。

7. 實體首部欄位

* 請求報文和響應報文的實體部分所用的首部,主要用來補充更新時間等相關信息。

* Allow:通知客戶端Request-URI所指定資源的所有HTTP方法。當伺服器收到不支持方法的請求時返回405 Method Not Allowed,伴隨著Allow欄位給出支持的方法表。

* Content-Encoding:告訴客戶端伺服器對實體部分的內容編碼方式。

* Content-Language:實體使用的自然語言。

* Content-Length:實體主體部分的大小(位元組),如果對實體主體進行編碼傳輸,則不能使用該首部。

* Content-Location:表示的是報文主體返回資源時對應的URI類似於請求首部裡面的Referer。

* Content-MD5:報文主體 -> MD5 -> BASE64 -> Content-MD5,來檢查報文主體在傳輸過程中是否完整,接收方接收到後也會進行一次MD5計算比對。但不能保證是否被篡改。因為篡改後可能MD5也被重新計算

* Content-Range:響應範圍請求,告訴客戶端實體屬於那個方位,例如,Content-Range:bytes 5001-10000/10000。

* Content-type:實體主體內對象的類型,charset表示字符集。例如,Content-type:text/html; charset=UTF-8。

* Expires:緩存過期時間。時間以內代理直接返回緩存,否則向源伺服器請求資源。可以設置為Date欄位相同值禁止代理對資源緩存。max-age會覆蓋Expires。

* Last-Modified:最終修改時間。

8. Cookie的首部欄位

* Cookie的工作機制是用戶識別及狀態管理。調用Cookie時由於可校驗Cookie的有效期,發送方的域,路徑,協議等信息,所以Cookie內的數據不會因為來自其他Web站點和攻擊者的攻擊而泄露。

* Set-Cookie(響應):

- NAME:Cookie的名稱。

- expires:指定Cookie的有效期;默認為瀏覽器關閉。Cookie一旦由伺服器發送到客戶端,則無法顯式刪除,僅能覆蓋。

- path:限制指定Cookie的發送範圍的文件目錄。可以避開,安全效果一般;

- domain:域名與domain指定值結尾匹配。除非針對多個domain發送Cookie,否則不指定更安全。

- secure:限制僅在HTTPS安全連接時纔可以發送Cookie。省略時HTTP和HTTPS均可用。

- HttpOnly:防止XSS攻擊,使得JavaScript無法獲得Cookie。JS的document.cookie無法讀取HttpOnly屬性的Cookie。

* Cookie(請求):客戶端希望獲取HTTP狀態管理支持。

9. 其他首部欄位

* HTTP首部欄位是可以自行擴展的

* X-Frame-Options:控制網站內容在其他web網站的Frame標籤內的顯示問題,防止點擊劫持攻擊。可以在apache中配置。

- DENY:拒絕

- SAMEORIGIN:僅在同源域名下的頁面

* X-XSS-Protection:響應首部,針對XSS攻擊的對策,0為無效,1為有效。

* DNT:請求首部,Do not Track,拒絕個人信息被收集,拒絕靶向廣告的一種方法。0表示同意,1表示拒絕。

* P3P:響應首部,保護個人隱私。

## 確保web安全的HTTPS

1. HTTP的缺點([使用wireshark抓包](PYTHON黑帽編程1.5 使用WIRESHARK練習網路協議分析)):

* 通信使用明文,內容會被監聽

* 不驗證對方身份,會被偽裝

* 無法驗證報文完整性,會被篡改

2. HTTPS(HTTP secure 或 HTTP over SSL):通過和SSL(Secure Socket Layer)或者TLS(Transport Layer Security)的組合使用,加密HTTP通信內容。用SSL建立安全通信線路後,在該線路上發送請求。([關於SSL和TLS](來風:ssl/tls是什麼?是怎麼工作的?))

3. 內容加密:僅加密報文主體不加密報文首部,要求客戶端和伺服器具有加密和解密的機制。不同於SSL或TLS將整個通信線路加密,這種加密方式仍有可能被篡改內容。

4. HTTP協議無論是誰發送的請求,都會返迴響應(可以設置訪問IP和埠限制),HTTP不驗證通信方身份有以下幾個問題:

* 無法確認伺服器是否被偽裝;

* 無法確認客戶端是否被偽裝;

* 無法確認通信方是否有訪問許可權;

* 無法判斷請求源;

* 無意義的請求也會響應,易被DoS攻擊。

* HTTPS通過SSL提供加密和證書,用於確認身份,防止被偽裝。

6. HTTP協議的報文可能被篡改(MITM攻擊 Man-in-the-Middle attack):

* HTTP採用MD5,SHA-1,PGP(Pretty Good Privacy)創建數字簽名和散列值來確保文件的正確性,但仍有可能被篡改。

* 需要HTTPS提供的加密和摘要服務

7. HTTPS = HTTP + 加密 + 認證 + 完整性保護:HTTPS就是身披SSL/TLS外殼的HTTP,在應用層HTTP與傳輸層TCP中間加了一層SSL。

8. HTTPS採用混合加密方式:傳遞對話密鑰(對稱加密)時使用非對稱加密方式,加解密對話信息時使用的是對稱加密生成的對話密鑰。因為公鑰加密與對稱加密相比,處理效率更低,所以僅用於傳遞對話密鑰。

9. HTTPS大致流程:

* 客戶端從伺服器處獲取伺服器公鑰(注意,公鑰傳遞可能被篡改);

* 客戶端生成一個隨機對話密鑰(對稱加密),並使用伺服器公鑰加密後發給伺服器;

* 伺服器使用私鑰解密獲取對話密鑰;

* 客戶端和伺服器使用相同的對話密鑰進行加密通信。

10. CA(Certificate Authority)介入:為防止第一步中公鑰傳遞被篡改需要第三方權威機構CA介入。介入流程為:

* 伺服器運營人員向CA提交公鑰並申請數字證書;

* CA驗證申請者身份後對使用自己的私鑰對申請者的公鑰做數字簽名,並公佈自己的公鑰。

* 伺服器將證書發給客戶端(DNS域名解析時完成),客戶端使用CA的公開密鑰驗證證書籤名,如果成功則:確認證書有效,伺服器的公開密鑰是可信的。

* 關鍵在於如何傳遞CA的公鑰給客戶端,一般情況下CA的公鑰會直接植入在瀏覽器內部。

11. EV SSL證書(Extended Validation SSL Certificate):基於國際標準的認證頒發的證書。防止用戶被釣魚攻擊。

12. 其他證書:客戶端證書,中級認證證書,自認證證書(OpenSSL服務)。

13. HTTP通信全過程:協商決定加密組件,發送公鑰證書,交換對話密鑰,開始HTTP通信。

* 客戶端發送ClientHello報文:客戶端支持的SSL版本,加密組件(Cipher Suite)(加密演算法和密鑰長度);

* 服務端此時回復3份報文:

- ServerHello:SSL版本以及加密組件(由客戶端要求篩選);

- Certificate報文:公鑰證書;

- ServerHelloDone報文:通知客戶端SSL第一次握手結束

* 客戶端發送3份報文:

- ClientKeyExchange報文:Pre-master-secret的隨機密碼串(使用伺服器公鑰加密);

- ChangeCipherSpec報文:提示伺服器今後用Pre-master-secret加密;

- Finished報文:至今全部報文的整體校驗值

* 伺服器收到後回復2份報文:

- ChangeCipherSpec報文;

- Finished報文:宣告第二次握手成功,至此SSL連接建立完成。

* 回到應用層,客戶端與伺服器開始用Pre-master-secret加密的HTTP協議通信,發送數據時會附加**MAC(Message Authentication Code)**的報文摘要,用以查知報文是否遭到篡改以保證完整性。

* 客戶端斷開連接,TCP四次揮手

14. HTTPS由於使用了SSL導致處理效率慢,比HTTP慢2到100倍:

* 通信慢:TCP與HTTP以外多加了一層SSL協議;

* 消耗資源:加密解密運算消耗硬體資源。

15. HTTPS與HTTP的選取:

* 機密場合使用HTTPS,HTTPS慢,需要CA認證費

* 一般情況使用HTTP。

## 確認訪問用戶身份的認證

1. HTTP認證方式:BASIC,DIGEST,SSL客戶端認證,FromBase認證(基於表單認證),Windows系統還有Keberos認證和NTLM認證。

2. BASIC認證:無法註銷,明文傳輸不安全,具體步驟如下:

* 如果需要BASIC認證,伺服器返回401和WWW-Authenticate以及Request-URI的安全域字元串realm;例如:WWW-Authenticate:Basic realm="Input Your ID and Password"。

* 客戶端發送ID:密碼 -> Base64編碼處理髮送給伺服器,例如,Authorization:Basic Z3Vlc3Q6Z3Vlc3Q=

* 伺服器驗證ID和密碼,成功返回200和資源,失敗返回401。

3. DIGEST認證:採用質詢/響應(challenge/response)方式,比BASIC安全,可以防竊聽但不可以防止偽裝。具體步驟:

- 伺服器返回401和WWW-Authenticate包含質問響應方式realm和臨時質詢碼(nonce,隨機字元串->Base64)

- 客戶端返回Authorization包含,username,realm,nonce,uri和response,其中realm和nonce與伺服器返回值相同,uri的值就是Request-URI,是為了防止Request-URI被代理修改,response也就Request-Digest存放經過MD5運算後的密碼字元

- 伺服器校驗,通過後返回Resquest-URI對應的資源。並在Authentication-Info寫入認證成功的相關信息。

4. SSL客戶端認證:藉由客戶端證書完成認證,需要購買SSL客戶端證書,具體步驟:

- 伺服器返回包含Certificate-Request欄位的報文,要求客戶端提交證書;

- 客戶端返回Client-Certificate提交證書;

- 伺服器驗證客戶端證書後,領取客戶端證書內密鑰開始HTTPS加密通信。

5. 表單認證:客戶端向伺服器的web應用程序上發送登陸信息(Credential),即一般的網頁登陸。表單認證並不定義在HTTP協議中。

6. SSL客戶端認證採用雙因素認證:SSL雙因素認證一般會和表單認證組合形成雙因素認證(Two-factor authentication)。SSL客戶端認證客戶端計算機,表單密碼認證認證用戶本人,確定正確的人用正確的計算機。

7. 認證大多是表單認證,BASIC認證和DIGEST認證幾乎不怎麼使用,SSL客戶端認證需要維持費用,難以普及。

8. Session管理和Cookie應用

* 基於表單認證一般會用Cookie來管理回話Session;

* 具體步驟:

- 表單登陸時,客戶端把用戶ID和密碼放入報文實體部分,以POST方式發送登陸請求;

- 伺服器web應用核實用戶登陸信息,發放用以識別用戶的Session ID,並把用戶狀態與Session ID綁定後記錄在伺服器端,響應中在Set-Cookie內寫入Session ID。(如果Session ID被盜走,對方便可以偽裝你的身份,需要用難以推測的字元串,伺服器也需要進行有效期管理,此外為了防止XSS攻擊,最好事先加上httponly);

- 客戶端收到Session ID後會把它作為Cookie保存在本地,以後的請求都會帶上Cookie。

- 伺服器通過Session ID識別用戶和他的狀態。

* 伺服器保存用戶密碼的一種方法:密碼+鹽 -> hash計算出散列值保存。

## 基於HTTP的功能追加協議

1. HTTP的瓶頸:

* 一個連接上只可以發送一個請求;

* 請求只能從客戶端開始,客戶端不能接受除響應以外的指定;

* 請求和響應首部沒有壓縮就發送,首部信息越多延遲越大;

* 發送過多冗長首部;

* 可任意選擇數據壓縮格式,而非強制壓縮。

2. Ajax的解決方案:

* Ajax(Asynchronous JavaScript and XML,非同步JavaScript與XML技術)利用JavaScript和DOM的操作,以達到Web頁面替換載入的非同步通信手段。與同步載入相比,它只替換一部分頁面,響應傳輸的數據量也會因此減少。

* 核心在與XMLHttpRequest的API,使用JavaScript調用遍可以進行HTTP通信,藉此以載入好的web頁面為基礎發起請求只更新局部頁面。減少每次更新全部頁面帶來的流量消耗。**但也會因此可能嘗試大量請求**。

3. Comet的解決方案:

* 請求來了以後,Comet不會立即響應,為了實現推送,它會先把響應掛起,一旦伺服器內容更新了,立馬給客戶端響應,模擬伺服器推送功能(Server Push)。實現大流量網站的數據同步功能(FaceBook,YouTube等)

* 為了保留響應,**一次連接的時間增長,維持連接也會消耗伺服器資源**。

4. SPDY的目標:

* Ajax和Comet都沒有從實質上解決HTTP協議的瓶頸,SPDY旨在從協議級別上改進HTTP;

* SPDY規定啟用SSL表示層來增強安全級別,SPDY以會話層的形式夾在HTTP應用層與SSL表示層之間。

* 使用SPDY後HTTP協議額外獲得以下功能:

- 多路復用流:單一TCP連接處理多個HTTP請求。TCP的處理效率提高;

- 賦予請求優先順序:分配優先順序解決在發送多個請求時因帶寬低導致響應變慢的問題;

- 壓縮HTTP首部:通信的數據包數量和發送的位元組數減少;

- 推送功能:伺服器可以直接發送數據不需要等待客戶端的請求;

- 伺服器提示功能:伺服器主動提示客戶端請求所需的資源,客戶端可以獲知資源的所在,因而可以避免發送不必要的請求,比如客戶端得知資源在緩存中。

* SPDY的問題:僅僅是把帶個域名(IP)的通信多路復用,當一個web網站使用多個域名下的資源時,改善效果就不明顯

5. 使用瀏覽器進行全雙工通信的WebSocket

* WebSocket:主要為瞭解決Ajax和Comet裏XMLHttpRequest附帶的缺陷所引起的問題。

* WebSocket協議:服務端與客戶端之間一旦建立起WebSocket協議的通信連接,之後所有的通信都依靠這個專業協議進行,可以發送Json,XML,HTML等各種格式的文件。

* WebSocket協議建立在HTTP基礎上,由客戶端發起,一旦建立,雙方都可以**直接**發送報文;

* WebSocket的主要特點:

- 推送功能:伺服器直接給客戶端發送報文;

- 減少通信量:一旦建立就一直保持,連接開銷減少,WebSocket的首部信息減少,通信量也減少了;

* WebSocket協議的創建:在HTTP連接建立之後需要完成一次握手:

- 用 Upgrade: websocket 欄位通知伺服器協議改變以達到握手,Sec-WebSocket-Key記錄握手必須的鍵值,Sec-WebSocket-Protocol記錄使用的子協議;

- 伺服器返回101 Switching Protocols,在響應報文中包含Sec-WebSocket-Accept欄位,內容為基於Sec-WebSocket-Key欄位值生成的字元串;

- 之後通信不採用HTTP,直接採用WebSocket獨立的數據幀。

* WebSocket API:可以用JavaScript調用。

6. HTTP/2.0

* HTTP/2.0的目標是改善用戶使用Web的速度體驗。

* 實現:SPDY,HTTP Speed + Mobility,Network-Friendly HTTP Upgrade

7. Web伺服器管理文件的WebDAV

* WebDAV(Web-Based Distributed Authoring and Versioning, 基於萬維網的分散式創作和版本控制):一個可對Web伺服器上的內容直接進行文件複製,編輯等操作的分散式文件系統,還具備創建者管理,加鎖,版本控制。拓展於HTTP/1.1

* 新增概念:集合,資源,屬性,鎖;

* 新增了大量方法和狀態碼;

## 構建Web內容的技術

1. HTML,XML(雨同屬於SGML(Standard Generalized Markup Language)),CSS,JavaScript,DOM

2. CGI是指Web伺服器收到客戶端發送來的請求後轉發給程序的一組機制,CGI程序一般用PHP,Perl,Ruby和C等語言編寫;

3. Servlet:一種能在伺服器上創建動態內容的程序

* 相較於CGI:每次接到請求CGI程序(進程級別)都要跟著啟動一次,因此一旦訪問量過大,web伺服器就要承擔較大負載。Servlet運行在Web伺服器相同進程中,因此負載較小。Servlet運行在Web容器或Servlet容器中。

4. XML的結構是用標籤分割而成的樹形結構,因此通過語法分析器(Parser)的解析功能解析XML結構並取出數據元素可以更容易地對數據進行讀取。

5. JSON(JavaScript Object Notation)是以JavaScript的對象表示法為基礎的輕量級數據標記語言。JSON的字元串可以直接被JavaScript輕易讀取。

## Web攻擊技術

1. 主動攻擊:SQL注入,OS注入;被動攻擊:XSS攻擊和跨站點請求偽造;

2. 輸出值轉義不完全引發的漏洞:客戶端驗證,輸入輸出值轉義,不應該使用JS做關鍵的輸入值驗證,因為客戶端可以關閉或篡改JS。

3. XSS攻擊:存在安全漏洞的Web網站上註冊用戶的瀏覽器內運行非法的HTML標籤或JS進行的一種攻擊。

* 在URI欄位中嵌入script腳本,通過e-mail發送給受害者;例如: example.jp/login?"><script>...<script>

* 盜取用戶Cookie:JS中調用document.cookie竊取用戶的Cookie信息。

4. SQL注入:利用字元替換中的漏洞運行web規定外的SQL代碼獲取不該獲得的信息;

5. OS注入:Web應用中如果調用shell來調用系統命令,如果調用Shell時存在漏洞,就可以執行非法OS命令;

6. HTTP首部攻擊(HTTP Header Injection):攻擊者在響應首部欄位內插入換行,添加任意響應首部或主體的一種攻擊;例如:下拉列表,每個列表一個ID值,選中列表元素,伺服器響應302 伴隨一個帶有該ID值的Location,瀏覽器立即重新訪問新的URI,此時如果替換ID值為ID%0D%0ASet-Cookie:+SID=123456789,%0D%0A會被轉義成換行,這樣攻擊者就成功地在響應中添加了Set-Cookie首部。

7. HTTP響應截斷攻擊(Response Splitting Attack):%0D%0A%0D%0A放一起則可以偽造出首部與主體之間的空行,這樣就可以偽造響應主體;

8. 郵件首部注入攻擊(Mail Header Injection):%0D%0A追加欄位cc,Bcc之類,修改郵件內容;

9. 目錄遍歷攻擊(Directory Traversal):通過相對路徑指定不該訪問的路徑,例如,http://example.com/read.php?log=../../etc/passwd;

10. 強制瀏覽:URL中暴露伺服器的文件路徑設計;

11. 異常消息拋出:給攻擊者提示,應該模糊處理;

12. 開放重定向:例如:Example Domain

13. 會話劫持(Session Hijack):攻擊者獲取到了用戶的會話ID,並偽裝用戶攻擊

14. 點擊劫持:利用透明UI矇騙用戶;

15. DoS攻擊:拒絕服務攻擊;


推薦閱讀:
相關文章