主頁 > 企業開發 > 前端必備的 HTTP 知識

前端必備的 HTTP 知識

2022-08-17 11:51:00 企業開發

HTTP 起源

HTTP 是由蒂姆·伯納斯-李(TimBerners—Lee)于1989年在歐洲核子研究組織(CERN)所發起

其中最著名的是 1999 年 6 月公布的 RFC 2616,定義了 HTTP 協議中現今廣泛使用的一個版本——HTTP 1.1

HTTP 是什么

全稱:超文本傳輸協議(HyperText Transfer Protocol

概念:HTTP 是一種能夠獲取像 HTML、圖片等網路資源的通訊協議(protocol),它是在 web 上進行資料交換的基礎,是一種 client-server 協議

HTTP——因特網的多媒體信使 ——《HTTP權威指南》,
HTTP 在因特網的角色:充當一個信使的角色,干的就是一個跑腿的活,在客戶端和服務端之間傳遞資訊,但我們又不能缺少它,HTTP 協議是應用層的協議,是與前端開發最息息相關的協議,平時我們遇到的 HTTP 請求、 HTTP 快取、Cookies、跨域等其實都跟 HTTP 息息相關

HTTP 的基礎特性

  • 可拓展協議,HTTP 1.0 出現的 HTTP headers 讓協議拓展變得更加的容易,只要服務端和客戶端就 headers 達成語意一致,新功能就可以被輕松的加入進來

  • HTTP 是無狀態的、有會話的,在同一個連接中,兩個執行成功的 HTTP 請求之間是沒有關系的,這就帶來了一個問題,用戶沒有辦法在同一個網站中進行連續的互動,比如在一個電商網站里,用戶把某個商品加入到購物車,切換一個頁面后再次添加了商品,這兩次添加商品的請求之間沒有關聯,瀏覽器無法知道用戶最終選擇了哪些商品,而使用 HTTP 的頭部擴展,HTTP Cookies 就可以解決這個問題,把 Cookies 添加到頭部中,創建一個會話讓每次請求都能共享相同的背景關系資訊,達成相同的狀態,

  • HTTP 與連接,通過 TCP,或者 TLS——加密的 TCP 連接來發送,理論上任何可靠的傳輸協議都可以使用,連接是傳輸層控制的,這從根本上來講不是 HTTP 的范疇,

也就是說,HTTP 依賴于面向連接的 TCP 進行訊息傳遞,但連接并不是必須的,只需要它是可靠的,或不丟失訊息的(至少回傳錯誤),

HTTP/1.0 默認為每一對 HTTP 請求/回應都打開一個單獨的 TCP 連接,當需要連續發起多個請求時,這種模式比多個請求共享同一個 TCP 鏈接更低效,為此,HTTP 1.1 持久連接的概念,底層 TCP 連接可以通過 connection 頭部實作,但 HTTP 1.1 在連接上也是不完美的,后面我們會提到,

基于 HTTP 的組件系統

HTTP 的組件系統包括客戶端、web 服務器和代理

image

客戶端:user-agent

瀏覽器,特殊比如是工程師使用的程式,以及 Web 開發人員除錯應用程式

Web服務端

Web Server 來服務并提供客戶端所請求的檔案,每一個發送到服務器的請求,都會被服務器處理并回傳一個訊息,也就是 response

代理(Proxies)

在瀏覽器和服務器之間,有很多計算機和其他設備轉發了 HTTP 訊息,它們可能出現在傳輸層、網路層和物理層上,對于 HTTP 應用層而言就是透明的

有如下的一些作用

  • 快取
  • 過濾(像防病毒掃描、家長控制)
  • 負載均衡
  • 認證(對不同的資源進行權限控制)
  • 日志管理

HTTP 報文組成

HTTP 有兩種型別的訊息:

  • 請求——由客戶端發送用來觸發一個服務器上的動作
  • 回應——來自服務器端的應答

HTTP 訊息由采用 ASCII 編碼的多行文本構成的,在 HTTP/1.1 以及更早的版本中,這些訊息通過連接公開的發送,在 HTTP2.0 中,訊息被分到了多個 HTTP 幀中,通過組態檔(用于代理服務器或者服務器),API(用于瀏覽器)或者其他介面提供 HTTP 訊息

典型的 HTTP 會話

  • 建立連接
    在客戶端-服務器協議中,連接是由客戶端發起建立的,在 HTTP 中打開連接意味著在底層傳輸層啟動連接,通常是 TCP,使用 TCP 時,HTTP 服務器的默認埠號是 80,另外還有 80008080 也很常用

  • 發送客戶端請求

  • 服務器回應請求

HTTP 請求和回應

HTTP 請求和回應都包括起始行(start line)、請求頭(HTTP Headers)、空行(empty line)以及 body 部分,如下圖所示:

image

  • 起始行,
    請求的起始行:請求方法、請求 PathHTTP 版本號
    回應的起始行:HTTP 版本號、回應狀態碼以及狀態文本描述

下面詳細說下請求 Path,請求路徑(Path)有以下幾種:

1)一個絕對路徑,末尾跟上一個 ' ? ' 和查詢字串,這是最常見的形式,稱為 原始形式 (origin form),被 GETPOSTHEADOPTIONS 方法所使用

POST / HTTP/1.1
GET /background.png HTTP/1.0
HEAD /test.html?query=alibaba HTTP/1.1
OPTIONS /anypage.html HTTP/1.0

2)一個完整的 URL,主要在使用 GET 方法連接到代理的時候使用

GET http://developer.mozilla.org/en-US/docs/Web/HTTP/Messages HTTP/1.1

3)由域名和可選埠(以':'為前綴)組成的 URLauthority component,稱為 authority form,僅在使用 CONNECT 建立 HTTP 隧道時才使用

CONNECT developer.mozilla.org:80 HTTP/1.1

4)星號形式 (asterisk form),一個簡單的星號('*'),配合 OPTIONS 方法使用,代表整個服務器,

OPTIONS * HTTP/1.1
  • Headers 請求頭或者回應頭,詳見下面的首部,
    不區分大小寫的字串,緊跟著的冒號 ('?? 和一個結構取決于 header 的值

  • 空行,很多人容易忽略

  • Body

請求 Body 部分:
有些請求將資料發送到服務器以便更新資料:常見的的情況是 POST 請求(包含 HTML 表單資料),請求報文的 Body 一般為兩類,一類是通過 Content-TypeContent-Length 定義的單檔案 body,另外一類是由多 Body 組成,通常是和 HTML Form 聯系在一起的,兩者的不同表現在于 Content-Type的值,

1)Content-Type —— application/x-www-form-urlencoded
對于 application/x-www-form-urlencoded 格式的表單內容,有以下特點:

I.其中的資料會被編碼成以&分隔的鍵值對

II.字符以URL編碼方式編碼,

// 轉換程序: {a: 1, b: 2} -> a=1&b=2 -> 如下(最終形式)
"a%3D1%26b%3D2"

2)Content-Type —— multipart/form-data

請求頭中的 Content-Type 欄位會包含 boundary,且 boundary 的值有瀏覽器默認指定,例: Content-Type: multipart/form-data;boundary=----WebkitFormBoundaryRRJKeWfHPGrS4LKe

資料會分為多個部分,每兩個部分之間通過分隔符來分隔,每部分表述均有 HTTP 頭部描述子包體,如Content-Type,在最后的分隔符會加上--表示結束,

Content-Disposition: form-data;name="data1";
Content-Type: text/plain
data1
----WebkitFormBoundaryRRJKeWfHPGrS4LKe
Content-Disposition: form-data;name="data2";
Content-Type: text/plain
data2
----WebkitFormBoundaryRRJKeWfHPGrS4LKe--

回應 Body 部分:

1)由已知長度的單個檔案組成,該型別 body 由兩個 header 定義:Content-TypeContent-Length

2)由未知長度的單個檔案組成,通過將 Transfer-Encoding 設定為 chunked 來使用 chunks 編碼,

關于 Content-Length 在下面 HTTP 1.0 中會提到,這個是 HTTP 1.0 中新增的非常重要的頭部,

方法

安全方法:HTTP 定義了一組被稱為安全方法的方法,GET 方法和 HEAD 方法都被認為是安全的,這意味著 GET 方法和 HEAD 方法都不會產生什么動作 —— HTTP 請求不會再服務端產生什么結果,但這并不意味著什么動作都沒發生,其實這更多的是 web 開發者決定的

  • GET:請求服務器發送某個資源
  • HEAD:跟 GET 方法類似,但服務器在回應中只回傳了首部,不會回傳物體的主體部分,
  • PUT:向服務器中寫入檔案,語意:用請求的主體部分來創建一個由所請求的 URL 命名的新檔案
  • POST:用來向服務器中輸入資料的,通常我們提交表單資料給服務器,【POST 用于向服務器發送資料,PUT 方法用于向服務器上的資源(例如檔案)中存盤資料】
  • TRACE:主要用于診斷,實作沿通向目標資源的路徑的訊息環回(loop-back)測驗 ,提供了一種實用的 debug 機制,
  • OPTIONS:請求 WEB 服務器告知其支持的各種功能,可以詢問服務器支持哪些方法,或者針對某些特殊資源支持哪些方法,
  • DELETE:請求服務器洗掉請求 URL 中指定的的資源

GET 和 POST 的區別

首先要了解下副作用和冪等的概念,副作用指的是對服務器端資源做修改,冪等指發送 MN 次請求(兩者不相同且都大于 1),服務器上資源的狀態一致,應用場景上,get是無副作用的,冪等的,post 主要是有副作用的,不冪等的情況

技術上有以下的區分:

  • 快取:Get 請求能快取,Post 請求不能
  • 安全:Get 請求沒有 Post 請求那么安全,因為請求都在 URL 中,且會被瀏覽器保存歷史紀錄,POST 放在請求體中,更加安全
  • 限制:URL 有長度限制,會干預 Get 請求,這個是瀏覽器決定的
  • 編碼:GET 請求只能進行 URL 編碼,只能接收 ASCII 字符,而 POST 沒有限制,POST 支持更多的編碼型別,而且不對資料型別做限制
  • TCP 的角度,GET 請求會把請求報文一次性發出去,而 POST 會分為兩個 TCP 資料包,首先發 header 部分,如果服務器回應 100(continue), 然后發 body 部分,(火狐瀏覽器除外,它的 POST 請求只發一個 TCP 包)

狀態碼

  • 100~199——資訊性狀態碼

    101 Switching Protocols,在HTTP升級為WebSocket的時候,如果服務器同意變更,就會發送狀態碼 101,

  • 200~299——成功狀態碼

    200 OK,表示從客戶端發來的請求在服務器端被正確處理

    204 No content,表示請求成功,但回應報文不含物體的主體部分

    205 Reset Content,表示請求成功,但回應報文不含物體的主體部分,但是與 204 回應不同在于要求請求方重置內容

    206 Partial Content,進行范圍請求

  • 300~399——重定向狀態碼

    301 moved permanently,永久性重定向,表示資源已被分配了新的 URL

    302 found,臨時性重定向,表示資源臨時被分配了新的 URL

    303 see other,表示資源存在著另一個 URL,應使用 GET 方法獲取資源

    304 not modified,表示服務器允許訪問資源,但因發生請求未滿足條件的情況

    307 temporary redirect,臨時重定向,和302含義類似,但是期望客戶端保持請求方法不變向新的地址發出請求

  • 400~499——客戶端錯誤狀態碼

    400 bad request,請求報文存在語法錯誤

    401 unauthorized,表示發送的請求需要有通過 HTTP 認證的認證資訊

    403 forbidden,表示對請求資源的訪問被服務器拒絕

    404 not found,表示在服務器上沒有找到請求的資源

  • 500~599——服務器錯誤狀態碼

    500 internal sever error,表示服務器端在執行請求時發生了錯誤

    501 Not Implemented,表示服務器不支持當前請求所需要的某個功能

    503 service unavailable,表明服務器暫時處于超負載或正在停機維護,無法處理請求

首部

HTTP Headers

1.通用首部(General headers)同時適用于請求和回應訊息,但與最終訊息主體中傳輸的資料無關的訊息頭,如 Date

2.請求首部(Request headers)包含更多有關要獲取的資源或客戶端本身資訊的訊息頭,如 User-Agent

3.回應首部(Response headers)包含有關回應的補充資訊

4.物體首部(Entity headers)含有關物體主體的更多資訊,比如主體長(Content-Length)度或其 MIME 型別,如 Accept-Ranges

詳細的 Header 見 HTTP Headers 集合

HTTP 的前世今生

HTTP(HyperText Transfer Protocol)是萬維網(World Wide Web)的基礎協議,Tim Berners-Lee 博士和他的團隊在1989-1991年間創造出它,【HTTP、網路瀏覽器、服務器】

在 1991 年發布了 HTTP 0.9 版,在 1996 年發布 1.0 版,1997 年是 1.1 版,1.1 版也是到今天為止傳輸最廣泛的版本,2015 年發布了 2.0 版,其極大的優化了 HTTP/1.1 的性能和安全性,而 2018 年發布的 3.0 版,繼續優化 HTTP/2,激進地使用 UDP 取代 TCP 協議,目前,HTTP/3 在 2019 年 9 月 26 日 被 ChromeFirefox,和 Cloudflare 支持

HTTP 0.9

單行協議,請求由單行指令構成,以唯一可用的方法 GET 開頭,后面跟的是目標資源的路徑

GET /mypage.html

回應:只包括回應檔案本身

<HTML>
這是一個非常簡單的HTML頁面
</HTML>
  • 沒有回應頭,只傳輸 HTML 檔案
  • 沒有狀態碼

HTTP 1.0

RFC 1945 提出了 HTTP1.0構建更好可拓展性

  • 協議版本資訊會隨著每個請求發送
  • 回應狀態碼
  • 引入了 HTTP 頭的概念,無論是請求還是拓展,允許傳輸元資料,使協議變得靈活,更加具有拓展性
  • Content-Type 請求頭,具備了傳輸除純文本 HTML 檔案以外其他型別檔案的能力
    在回應中,Content-Type 標頭告訴客戶端實際回傳的內容的內容型別

媒體型別是一種標準,用來表示檔案、檔案或者位元組流的性質和格式,瀏覽器通常使用 MIMEMultipurpose Internet Mail Extensions )型別來確定如何處理 URL,因此 Web 服務器在回應頭中配置正確的 MIME 型別會非常的重要,如果配置不正確,可能會導致網站無法正常的作業,MIME 的組成結構非常簡單;由型別與子型別兩個字串中間用'/'分隔而組成,

HTTPMIME type 取了一部分來標記報文 body 部分的資料型別,這些型別體現在Content-Type 這個欄位,當然這是針對于發送端而言,接收端想要收到特定型別的資料,也可以用 Accept 欄位,

這兩個欄位的取值可以分為下面幾類:

- text: text/html, text/plain, text/css 等
- image: image/gif, image/jpeg, image/png 等
- audio/video: audio/mpeg, video/mp4 等
- application: application/json, application/javascript, application/pdf, application/octet-stream

同時為了約定請求的資料和回應資料的壓縮方式、支持語言、字符集等,還提出了以下的 Header

1.壓縮方式:發送端:Content-Encoding(服務端告知客戶端,服務器對物體的主體部分的編碼方式) 和 接收端:Accept-Encoding(用戶代理支持的編碼方式),值有 gzip: 當今最流行的壓縮格式;deflate: 另外一種著名的壓縮格式;br: 一種專門為 HTTP 發明的壓縮演算法

2.支持語言:Content-LanguageAccept-Language(用戶代理支持的自然語言集)

3.字符集:發送端:Content-Type 中,以 charset 屬性指定,接收端: Accept-Charset(用戶代理支持的字符集),

// 發送端
Content-Encoding: gzip
Content-Language: zh-CN, zh, en
Content-Type: text/html; charset=utf-8

// 接收端
Accept-Encoding: gzip
Accept-Language: zh-CN, zh, en
Accept-Charset: charset=utf-8

雖然 HTTP1.0HTTP 0.9 的基礎上改進了很多,但還是存在這不少的缺點

HTTP/1.0 版的主要缺點是,每個 TCP 連接只能發送一個請求,發送資料完畢,連接就關閉,如果還要請求其他資源,就必須再新建一個連接,
TCP 連接的新建成本很高,因為需要客戶端和服務器三次握手,并且開始時發送速率較慢(slow start),

HTTP 最早期的模型,也是 HTTP/1.0 的默認模型,是短連接,每一個 HTTP 請求都由它自己獨立的連接完成;這意味著發起每一個 HTTP 請求之前都會有一次 TCP 握手,而且是連續不斷的,

HTTP 1.1

HTTP/1.1 在1997年1月以 RFC 2068 檔案發布,

HTTP 1.1 消除了大量歧義內容并引入了多項技術

  • 連接可以復用,長連接:connection: keep-aliveHTTP 1.1 支持長連接(PersistentConnection),在一個 TCP 連接上可以傳送多個 HTTP 請求和回應,減少了建立和關閉連接的消耗和延遲,在 HTTP1.1 中默認開啟 Connection: keep-alive,一定程度上彌補了 HTTP1.0 每次請求都要創建連接的缺點,

  • 增加了管道化技術(HTTP Pipelinling),允許在第一個應答被完全發送完成之前就發送第二個請求,以降低通信延遲,復用同一個 TCP 連接期間,即便是通過管道同時發送了多個請求,服務端也是按請求的順序依次給出回應的;而客戶端在未收到之前所發出所有請求的回應之前,將會阻塞后面的請求(排隊等待),這稱為"隊頭堵塞"(Head-of-line blocking),

  • 支持回應分塊,分塊編碼傳輸:Transfer-Encoding: chunked
    Content-length 宣告本次回應的資料長度,keep-alive 連接可以先后傳送多個回應,因此用 Content-length 來區分資料包是屬于哪一個回應,
    使用 Content-Length 欄位的前提條件是,服務器發送回應之前,必須知道回應的資料長度, 對于一些很耗時的動態操作來說,這意味著,服務器要等到所有操作完成,才能發送資料,顯然這樣的效率不高,更好的處理方法是,產生一塊資料,就發送一塊,采用"流模式"(Stream)取代"快取模式"(Buffer),因此,HTTP 1.1 規定可以不使用 Content-Length 欄位,而使用"分塊傳輸編碼"(Chunked Transfer Encoding),只要請求或回應的頭資訊有 Transfer-Encoding: chunked 欄位,就表明 body 將可能由數量未定的多個資料塊組成,
    每個資料塊之前會有一行包含一個 16 進制數值,表示這個塊的長度;最后一個大小為 0 的塊,就表示本次回應的資料發送完了,

  • 引入額外的快取控制機制,在 HTTP1.0 中主要使用 header 里的 If-Modified-Since,Expires 等來做為快取判斷的標準,HTTP1.1 則引入了更多的快取控制策略例如 Entity tag, If-None-MatchCache-Control 等更多可供選擇的快取頭來控制快取策略,

  • Host 頭,不同的域名配置同一個 IP 地址的服務器,HostHTTP 1.1 協議中新增的一個請求頭,主要用來實作虛擬主機技術,

虛擬主機(virtual hosting)即共享主機(shared web hosting),可以利用虛擬技術把一臺完整的服務器分成若干個主機,因此可以在單一主機上運行多個網站或服務,

舉個栗子,有一臺 ip 地址為 61.135.169.125 的服務器,在這臺服務器上部署著谷歌、百度、淘寶的網站,為什么我們訪問 https://www.google.com 時,看到的是 Google 的首頁而不是百度或者淘寶的首頁?原因就是 Host 請求頭決定著訪問哪個虛擬主機,

HTTP 2.0

2015年,HTTP2.0 面世,rfc7540

  • HTTP/2 是二進制協議而不是文本協議,先來看幾個概念:
    • 幀:客戶端與服務器通過交換幀來通信,幀是基于這個新協議通信的最小單位,
    • 訊息:是指邏輯上的 HTTP 訊息,比如請求、回應等,由一或多個幀組成,
    • 流:流是連接中的一個虛擬信道,可以承載雙向的訊息;每個流都有一個唯一的整數識別符號

HTTP 2.0 中的幀將 HTTP/1.x 訊息分成幀并嵌入到流 (stream) 中,資料幀和報頭幀分離,這將允許報頭壓縮,將多個流組合,這是一個被稱為多路復用 (multiplexing) 的程序,它允許更有效的底層 TCP 連接,

也就是說,流用來承載訊息,訊息又是有一個或多個幀組成,二進制傳輸的方式更加提升了傳輸性能,
每個資料流都以訊息的形式發送,而訊息又由一個或多個幀組成, 幀是流中的資料單位,

HTTP 幀現在對 Web 開發人員是透明的,在 HTTP/2 中,這是一個在 HTTP/1.1 和底層傳輸協議之間附加的步驟,Web 開發人員不需要在其使用的 API 中做任何更改來利用 HTTP 幀;當瀏覽器和服務器都可用時,HTTP/2 將被打開并使用,

  • 這是一個復用協議,并行的請求能在同一個連接中處理,移除了 HTTP/1.x 中順序和阻塞的約束,多路復用允許同時通過單一的 HTTP/2 連接發起多重的請求-回應訊息

之前我們提到,雖然 HTTP 1.1 有了長連接和管道化的技術,但是還是會存在 隊頭阻塞,而 HTTP 2.0 就解決了這個問題
HTTP/2 中新的二進制分幀層突破了這些限制,實作了完整的請求和回應復用:客戶端和服務器可以將 HTTP 訊息分解為互不依賴的幀,然后交錯發送,最后再在另一端把它們重新組裝起來,

如上圖所示,快照捕捉了同一個連接內并行的多個資料流, 客戶端正在向服務器傳輸一個 DATA 幀(資料流 5),與此同時,服務器正向客戶端交錯發送資料流 1 和資料流 3 的一系列幀,因此,一個連接上同時有三個并行資料流,

將 HTTP 訊息分解為獨立的幀,交錯發送,然后在另一端重新組裝是 HTTP 2 最重要的一項增強,事實上,這個機制會在整個網路技術堆疊中引發一系列連鎖反應,從而帶來巨大的性能提升,讓我們可以:
1.并行交錯地發送多個請求,請求之間互不影響,
2.并行交錯地發送多個回應,回應之間互不干擾,
3.使用一個連接并行發送多個請求和回應,
4.消除不必要的延遲和提高現有網路容量的利用率,從而減少頁面加載時間,
5.不必再為繞過 HTTP/1.x 限制而做很多作業(比如精靈圖)
...

連接共享,即每一個 request 都是是用作連接共享機制的,一個 request 對應一個 id,這樣一個連接上可以有多個 request,每個連接的 request 可以隨機的混雜在一起,接收方可以根據 requestidrequest 再歸屬到各自不同的服務端請求里面,

HTTP 1.1HTTP 2.0 的對比,可以參考這個 網站 demo 演示

HTTP 1.1 演示如下:

HTTP2.0 演示如下:

  • 壓縮了headersHTTP1.xheader 帶有大量資訊,而且每次都要重復發送,就造成了性能的損耗, 為了減少此開銷和提升性能,HTTP/2 使用 HPACK 壓縮格式壓縮請求和回應標頭元資料,這種格式采用兩種簡單但是強大的技術:
    這種格式支持通過靜態霍夫曼代碼對傳輸的標頭欄位進行編碼,從而減小了各個傳輸的大小,
    這種格式要求客戶端和服務器同時維護和更新一個包含之前見過的標頭欄位的索引串列(換句話說,它可以建立一個共享的壓縮背景關系),此串列隨后會用作參考,對之前傳輸的值進行有效編碼,

  • 服務端推送,其允許服務器在客戶端快取中填充資料,通過一個叫服務器推送的機制來提前請求,服務器向客戶端推送資源無需客戶端明確地請求,服務端可以提前給客戶端推送必要的資源,這樣可以減少請求延遲時間,例如服務端可以主動把 JSCSS 檔案推送給客戶端,而不是等到 HTML 決議到資源時發送請求,這樣可以減少延遲時間大致程序如下圖所示:

如何升級你的 HTTP 版本

使用 HTTP/1.1HTTP/2 對于站點和應用來說是透明的,擁有一個最新的服務器和新點的瀏覽器進行互動就足夠了,只有一小部分群體需要做出改變,而且隨著陳舊的瀏覽器和服務器的更新,而不需 Web 開發者做什么,用的人自然就增加了

HTTPS

HTTPS 也是通過 HTTP 協議進行傳輸資訊,但是采用了 TLS 協議進行了加密

對稱加密和非對稱加密

對稱加密就是兩邊擁有相同的秘鑰,兩邊都知道如何將密文加密解密,但是因為傳輸資料都是走的網路,如果將秘鑰通過網路的方式傳遞的話,一旦秘鑰被截獲就沒有加密的意義的

非對稱加密

公鑰大家都知道,可以用公鑰加密資料,但解密資料必須使用私鑰,私鑰掌握在頒發公鑰的一方,首先服務端將公鑰發布出去,那么客戶端是知道公鑰的,然后客戶端創建一個秘鑰,并使用公鑰加密,發送給服務端,服務端接收到密文以后通過私鑰解密出正確的秘鑰

TLS 握手程序

TLS 握手的程序采用的是非對稱加密

  • Client Hello: 客戶端發送一個隨機值(Random1)以及需要的協議和加密方式,
  • Server Hello 以及 Certificate: 服務端收到客戶端的隨機值,自己也產生一個隨機值(Random2),并根據客戶端需求的協議和加密方式來使用對應的方式,并且發送自己的證書(如果需要驗證客戶端證書需要說明)
  • Certificate Verify: 客戶端收到服務端的證書并驗證是否有效,驗證通過會再生成一個隨機值(Random3),通過服務端證書的公鑰去加密這個隨機值并發送給服務端,如果服務端需要驗證客戶端證書的話會附帶證書
  • Server 生成 secret: 服務端收到加密過的隨機值并使用私鑰解密獲得第三個隨機值(Random3),這時候兩端都擁有了三個隨機值,可以通過這三個隨機值按照之前約定的加密方式生成密鑰,接下來的通信就可以通過該密鑰來加密解密

HTTP 快取

強快取

強快取主要是由 Cache-controlExpires 兩個 Header 決定的

Expires 的值和頭里面的 Date 屬性的值來判斷是否快取還有效,ExpiresWeb 服務器回應訊息頭欄位,在回應 http 請求時告訴瀏覽器在過期時間前瀏覽器可以直接從瀏覽器快取取資料,而無需再次請求,Expires 的一個缺點就是,回傳的到期時間是服務器端的時間,這是一個絕對的時間,這樣存在一個問題,如果客戶端的時間與服務器的時間相差很大(比如時鐘不同步,或者跨時區),那么誤差就很大,

Cache-Control 指明當前資源的有效期,控制瀏覽器是否直接從瀏覽器快取取資料還是重新發請求到服務器取資料,但是其設定的是一個相對時間,

指定過期時間:max-age 是距離請求發起的時間的秒數,比如下面指的是距離發起請求 31536000S 內都可以命中強快取

Cache-Control: max-age=31536000

表示沒有快取

Cache-Control: no-store

有快取但要重新驗證

Cache-Control: no-cache

私有和公共快取

public 表示回應可以被任何中間人(比如中間代理、CDN 等快取)
private 則表示該回應是專用于某單個用戶的,中間人不能快取此回應,該回應只能應用于瀏覽器私有快取中,

Cache-Control: private
Cache-Control: public

驗證方式:以下表示一旦資源過期(比如已經超過 max-age),在成功向原始服務器驗證之前,快取不能用該資源回應后續請求

Cache-Control: must-revalidate

Cache-control 優先級比 Expires 優先級高

以下是一個 Cache-Control 強快取的程序:

  • 首次請求,直接從 server 中獲取,其中會設定 max-age=100
  • 第二次請求,age=10,小于 100,則命中 Cache,直接回傳
  • 第三次請求,age=110,大于 110,強快取失效,就需要再次請求 Server

協商快取

  • If-Modified-Since——Last-Modified

Last-Modified 表示本地檔案最后修改日期,瀏覽器會在 request header 加上 If-Modified-Since(上次回傳的 Last-Modified 的值),詢問服務器在該日期后資源是否有更新,有更新的話就會將新的資源發送回來

但是如果在本地打開快取檔案,就會造成 Last-Modified 被修改,所以在 HTTP / 1.1 出現了 ETag

  • If-none-match——ETags

Etag 就像一個指紋,資源變化都會導致 ETag 變化,跟最后修改時間沒有關系,ETag 可以保證每一個資源是唯一的,If-None-Matchheader 會將上次回傳的 Etag 發送給服務器,詢問該資源的 Etag 是否有更新,有變動就會發送新的資源回來

If-none-matchETags 優先級高于 If-Modified-Since、Last-Modified

第一次請求:

第二次請求相同網頁:

協商快取,假如沒有改動的話,回傳 304 ,改動了回傳 200 資源

  • 200:強快取 Expires/Cache-Control 失效時,回傳新的資源檔案
  • 200 (from cache): 強緩 Expires/Cache-Control 兩者都存在,未過期,Cache-Control 優先 Expires 時,瀏覽器從本地獲取資源成功
  • 304 (Not Modified):協商快取 Last-modified/Etag 沒有過期時,服務端回傳狀態碼304

現在的200(from cache)已經變成了 disk cache(磁盤快取)和 memory cache(記憶體快取)兩種

revving 技術

上面提到 HTTP 快取相關,但是很多有時候,我們希望上線之后需要更新線上資源,

web 開發者發明了一種被 Steve Souders 稱之為 revving 的技術,不頻繁更新的檔案會使用特定的命名方式:在 URL 后面(通常是檔案名后面)會加上版本號,

弊端:更新了版本號,所有參考這些的資源的地方的版本號都要改變

web 開發者們通常會采用自動化構建工具在實際作業中完成這些瑣碎的作業,當低頻更新的資源(js/css)變動了,只用在高頻變動的資源檔案(html)里做入口的改動,

Cookies

HTTP Cookie(也叫 Web Cookie 或瀏覽器 Cookie)是服務器發送到用戶瀏覽器并保存在本地的一小塊資料,它會在瀏覽器下次向同一服務器再發起請求時被攜帶并發送到服務器上,

Set-Cookie 回應頭部和 Cookie 請求頭部

Set-Cookie: <cookie名>=<cookie值>

會話期Cookie

會話期Cookie是最簡單的 Cookie:瀏覽器關閉之后它會被自動洗掉,也就是說它僅在會話期內有效,會話期 Cookie 不需要指定過期時間(Expires)或者有效期(Max-Age),需要注意的是,有些瀏覽器提供了會話恢復功能,這種情況下即使關閉了瀏覽器,會話期 Cookie 也會被保留下來,就好像瀏覽器從來沒有關閉一樣

持久性Cookie

和關閉瀏覽器便失效的會話期 Cookie 不同,持久性 Cookie 可以指定一個特定的過期時間(Expires)或有效期(Max-Age),

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;

Cookie的Secure和HttpOnly 標記

標記為 SecureCookie 只應通過被 HTTPS 協議加密過的請求發送給服務端,

標記為 SecureCookie 只應通過被 HTTPS 協議加密過的請求發送給服務端,但即便設定了 Secure 標記,敏感資訊也不應該通過 Cookie 傳輸,因為 Cookie 有其固有的不安全性,Secure 標記也無法提供確實的安全保障

通過 JavaScriptDocument.cookie API 是無法訪問帶有 HttpOnly 標記的 cookie,這么做是為了避免跨域腳本攻擊(XSS

Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

Cookie的作用域

DomainPath 標識定義了 Cookie 的作用域:即 Cookie 應該發送給哪些 URL

Domain 標識指定了哪些主機可以接受 Cookie,如果不指定,默認為當前的主機(不包含子域名),如果指定了 Domain,則一般包含子域名,

例如,如果設定 Domain=mozilla.org,則 Cookie 也包含在子域名中(如developer.mozilla.org),

Path 標識指定了主機下的哪些路徑可以接受 Cookie(該 URL 路徑必須存在于請求 URL 中),以字符 %x2F ("/") 作為路徑分隔符,子路徑也會被匹配,

例如,設定 Path=/docs,則以下地址都會匹配:

/docs
/docs/Web/
/docs/Web/HTTP

SameSite Cookies

SameSite Cookie 允許服務器要求某個 cookie 在跨站請求時不會被發送,從而可以阻止跨站請求偽造攻擊

  • None 瀏覽器會在同站請求、跨站請求下繼續發送 cookies,不區分大小寫,【舊版本 chrome 默認 Chrome 80 版本之前】
  • Strict 瀏覽器將只在訪問相同站點時發送 cookie
  • Lax 將會為一些跨站子請求保留,如圖片加載或者 frames 的呼叫,但只有當用戶從外部站點導航到 URL 時才會發送,如 link 鏈接
Set-Cookie: key=value; SameSite=Strict

None Strict Lax

在新版本的瀏覽器(Chrome 80 之后)中,SameSite 的默認屬性是 SameSite=Lax,換句話說,當 Cookie 沒有設定 SameSite 屬性時,將會視作 SameSite 屬性被設定為 Lax —— 這意味著 Cookies 將不會在當前用戶使用時被自動發送,如果想要指定 Cookies 在同站、跨站請求都被發送,那么需要明確指定SameSiteNone,因為這一點,我們需要好好排查舊系統是否明確指定 SameSite,以及推薦新系統明確指定 SameSite,以兼容新舊版本 Chrome

更多 cookie 相關,可以查看我之前總結的一篇關于 cookie 的文章 前端須知的 Cookie 知識小結

HTTP訪問控制(CORS)

跨域資源共享(CORS)是一種機制,它使用額外的 HTTP 頭告訴瀏覽器,讓運行在一個 origin (domain) 上的 web 應用被準許訪問來自不同源服務器上的指定的資源

跨域資源共享標準新增了一組 HTTP 首部欄位,允許服務器宣告哪些源站通過瀏覽器有權限訪問哪些資源,

簡單請求

簡單請求(不會觸發 CORS 的預檢請求)需要同時滿足以下三點:

  • 方法是 GET/HEAD/POST 之一

  • Content-Type 的值僅限 text/plainmultipart/form-dataapplication/x-www-form-urlencoded 三者之一

  • HTTP 頭部不能超過以下欄位:AcceptAccept-LanguageContent-Language
    Content-Type(需要注意額外的限制)DPRDownlinkSave-DataViewport-WidthWidth

以下為一個簡單請求的請求報文以及回應報文

簡化以下:

請求首部欄位 Origin 表明該請求來源于 http://foo.example

本例中,服務端回傳的 Access-Control-Allow-Origin: * 表明,該資源可以被任意外域訪問,如果服務端僅允許來自 http://foo.example 的訪問,該首部欄位的內容如下:

Access-Control-Allow-Origin: http://foo.example

Access-Control-Allow-Origin 應當為 * 或者包含由 Origin 首部欄位所指明的域名,

預檢請求

規范要求,對那些可能對服務器資料產生副作用的 HTTP 請求方法,瀏覽器必須首先使用 OPTIONS 方法發起一個預檢請求(preflight request),從而獲知服務端是否允許該跨域請求,

服務器確認允許之后,才發起實際的 HTTP 請求,在預檢請求的回傳中,服務器端也可以通知客戶端,是否需要攜帶身份憑證(包括 CookiesHTTP 認證相關資料)

預檢請求中同時攜帶了下面兩個首部欄位:

Access-Control-Request-Method: POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type

首部欄位 Access-Control-Request-Method 告知服務器,實際請求將使用 POST 方法,首部欄位 Access-Control-Request-Headers 告知服務器,實際請求將攜帶兩個自定義請求首部欄位:X-PINGOTHERContent-Type,服務器據此決定,該實際請求是否被允許,

預檢請求的回應中,包括了以下幾個欄位

Access-Control-Allow-Origin: http://foo.example
// 表明服務器允許客戶端使用 POST, GET 和 OPTIONS 方法發起請求
Access-Control-Allow-Methods: POST, GET, OPTIONS
// 表明服務器允許請求中攜帶欄位 X-PINGOTHER 與 Content-Type
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
// 表明該回應的有效時間為 86400 秒,也就是 24 小時,在有效時間內,瀏覽器無須為同一請求再次發起預檢請求,
Access-Control-Max-Age: 86400

一般而言,對于跨域 XMLHttpRequestFetch 請求,瀏覽器不會發送身份憑證資訊,如果要發送憑證資訊,需要設定 XMLHttpRequest 的某個特殊標志位,比如說 XMLHttpRequestwithCredentials 標志設定為 true,則可以發送 cookie 到服務端,

對于附帶身份憑證的請求,服務器不得設定 Access-Control-Allow-Origin 的值為“*”,
這是因為請求的首部中攜帶了 Cookie 資訊,如果 Access-Control-Allow-Origin 的值為“*”,請求將會失敗,而將 Access-Control-Allow-Origin 的值設定為 http://foo.example,則請求將成功執行,

CORS 涉及到的請求和回應頭如下:
HTTP 回應首部欄位

  • Access-Control-Allow-Origin 允許訪問該資源的外域 URI,對于不需要攜帶身份憑證的請求,服務器可以指定該欄位的值為通配符,表示允許來自所有域的請求,
  • Access-Control-Expose-Headers 頭讓服務器把允許瀏覽器訪問的頭放入白名單
  • Access-Control-Max-Age 頭指定了 preflight 請求的結果能夠被快取多久
  • Access-Control-Allow-Credentials 頭指定了當瀏覽器的 credentials 設定為 true 時是否允許瀏覽器讀取 response 的內容,
  • Access-Control-Allow-Methods 首部欄位用于預檢請求的回應,其指明了實際請求所允許使用的 HTTP 方法,
  • Access-Control-Allow-Headers 首部欄位用于預檢請求的回應,其指明了實際請求中允許攜帶的首部欄位,

HTTP 請求首部欄位

  • Origin 首部欄位表明預檢請求或實際請求的源站
  • Access-Control-Request-Method 首部欄位用于預檢請求,其作用是,將實際請求所使用的 HTTP 方法告訴服務器,
  • Access-Control-Request-Headers 首部欄位用于預檢請求,其作用是,將實際請求所攜帶的首部欄位告訴服務器,

參考

  • MDN
  • HTTP的發展
  • HTTP概述
  • HTTP/2 簡介
  • 快取(二)——瀏覽器快取機制:強快取、協商快取
  • (建議精讀)HTTP靈魂之問,鞏固你的 HTTP 知識體系

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/502027.html

標籤:其他

上一篇:多行文本下的文字漸隱消失術

下一篇:使用three.js(webgl)搭建智慧樓宇、設備檢測、數字孿生——第十三課

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • IEEE1588PTP在數字化變電站時鐘同步方面的應用

    IEEE1588ptp在數字化變電站時鐘同步方面的應用 京準電子科技官微——ahjzsz 一、電力系統時間同步基本概況 隨著對IEC 61850標準研究的不斷深入,國內外學者提出基于IEC61850通信標準體系建設數字化變電站的發展思路。數字化變電站與常規變電站的顯著區別在于程序層傳統的電流/電壓互 ......

    uj5u.com 2020-09-10 03:51:52 more
  • HTTP request smuggling CL.TE

    CL.TE 簡介 前端通過Content-Length處理請求,通過反向代理或者負載均衡將請求轉發到后端,后端Transfer-Encoding優先級較高,以TE處理請求造成安全問題。 檢測 發送如下資料包 POST / HTTP/1.1 Host: ac391f7e1e9af821806e890 ......

    uj5u.com 2020-09-10 03:52:11 more
  • 網路滲透資料大全單——漏洞庫篇

    網路滲透資料大全單——漏洞庫篇漏洞庫 NVD ——美國國家漏洞庫 →http://nvd.nist.gov/。 CERT ——美國國家應急回應中心 →https://www.us-cert.gov/ OSVDB ——開源漏洞庫 →http://osvdb.org Bugtraq ——賽門鐵克 →ht ......

    uj5u.com 2020-09-10 03:52:15 more
  • 京準講述NTP時鐘服務器應用及原理

    京準講述NTP時鐘服務器應用及原理京準講述NTP時鐘服務器應用及原理 安徽京準電子科技官微——ahjzsz 北斗授時原理 授時是指接識訓通過某種方式獲得本地時間與北斗標準時間的鐘差,然后調整本地時鐘使時差控制在一定的精度范圍內。 衛星導航系統通常由三部分組成:導航授時衛星、地面檢測校正維護系統和用戶 ......

    uj5u.com 2020-09-10 03:52:25 more
  • 利用北斗衛星系統設計NTP網路時間服務器

    利用北斗衛星系統設計NTP網路時間服務器 利用北斗衛星系統設計NTP網路時間服務器 安徽京準電子科技官微——ahjzsz 概述 NTP網路時間服務器是一款支持NTP和SNTP網路時間同步協議,高精度、大容量、高品質的高科技時鐘產品。 NTP網路時間服務器設備采用冗余架構設計,高精度時鐘直接來源于北斗 ......

    uj5u.com 2020-09-10 03:52:35 more
  • 詳細解讀電力系統各種對時方式

    詳細解讀電力系統各種對時方式 詳細解讀電力系統各種對時方式 安徽京準電子科技官微——ahjzsz,更多資料請添加VX 衛星同步時鐘是我京準公司開發研制的應用衛星授時時技術的標準時間顯示和發送的裝置,該裝置以M國全球定位系統(GLOBAL POSITIONING SYSTEM,縮寫為GPS)或者我國北 ......

    uj5u.com 2020-09-10 03:52:45 more
  • 如何保證外包團隊接入企業內網安全

    不管企業規模的大小,只要企業想省錢,那么企業的某些服務就一定會采用外包的形式,然而看似美好又經濟的策略,其實也有不好的一面。下面我通過安全的角度來聊聊使用外包團的安全隱患問題。 先看看什么服務會使用外包的,最常見的就是話務/客服這種需要大量重復性、無技術性的服務,或者是一些銷售外包、特殊的職能外包等 ......

    uj5u.com 2020-09-10 03:52:57 more
  • PHP漏洞之【整型數字型SQL注入】

    0x01 什么是SQL注入 SQL是一種注入攻擊,通過前端帶入后端資料庫進行惡意的SQL陳述句查詢。 0x02 SQL整型注入原理 SQL注入一般發生在動態網站URL地址里,當然也會發生在其它地發,如登錄框等等也會存在注入,只要是和資料庫打交道的地方都有可能存在。 如這里http://192.168. ......

    uj5u.com 2020-09-10 03:55:40 more
  • [GXYCTF2019]禁止套娃

    git泄露獲取原始碼 使用GET傳參,引數為exp 經過三層過濾執行 第一層過濾偽協議,第二層過濾帶引數的函式,第三層過濾一些函式 preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'] (?R)參考當前正則運算式,相當于匹配函式里的引數 因此傳遞 ......

    uj5u.com 2020-09-10 03:56:07 more
  • 等保2.0實施流程

    流程 結論 ......

    uj5u.com 2020-09-10 03:56:16 more
最新发布
  • 使用Django Rest framework搭建Blog

    在前面的Blog例子中我們使用的是GraphQL, 雖然GraphQL的使用處于上升趨勢,但是Rest API還是使用的更廣泛一些. 所以還是決定回到傳統的rest api framework上來, Django rest framework的官網上給了一個很好用的QuickStart, 我參考Qu ......

    uj5u.com 2023-04-20 08:17:54 more
  • 記錄-new Date() 我忍你很久了!

    這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 大家平時在開發的時候有沒被new Date()折磨過?就是它的諸多怪異的設定讓你每每用的時候,都可能不小心踩坑。造成程式意外出錯,卻一下子找不到問題出處,那叫一個煩透了…… 下面,我就列舉它的“四宗罪”及應用思考 可惡的四宗罪 1. Sa ......

    uj5u.com 2023-04-20 08:17:47 more
  • 使用Vue.js實作文字跑馬燈效果

    實作文字跑馬燈效果,首先用到 substring()截取 和 setInterval計時器 clearInterval()清除計時器 效果如下: 實作代碼如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta ......

    uj5u.com 2023-04-20 08:12:31 more
  • JavaScript 運算子

    JavaScript 運算子/運算子 在 JavaScript 中,有一些運算子可以使代碼更簡潔、易讀和高效。以下是一些常見的運算子: 1、可選鏈運算子(optional chaining operator) ?.是可選鏈運算子(optional chaining operator)。?. 可選鏈操 ......

    uj5u.com 2023-04-20 08:02:25 more
  • CSS—相對單位rem

    一、概述 rem是一個相對長度單位,它的單位長度取決于根標簽html的字體尺寸。rem即root em的意思,中文翻譯為根em。瀏覽器的文本尺寸一般默認為16px,即默認情況下: 1rem = 16px rem布局原理:根據CSS媒體查詢功能,更改根標簽的字體尺寸,實作rem單位隨螢屏尺寸的變化,如 ......

    uj5u.com 2023-04-20 08:02:21 more
  • 我的第一個NPM包:panghu-planebattle-esm(胖虎飛機大戰)使用說明

    好家伙,我的包終于開發完啦 歡迎使用胖虎的飛機大戰包!! 為你的主頁添加色彩 這是一個有趣的網頁小游戲包,使用canvas和js開發 使用ES6模塊化開發 效果圖如下: (覺得圖片太sb的可以自己改) 代碼已開源!! Git: https://gitee.com/tang-and-han-dynas ......

    uj5u.com 2023-04-20 08:01:50 more
  • 如何在 vue3 中使用 jsx/tsx?

    我們都知道,通常情況下我們使用 vue 大多都是用的 SFC(Signle File Component)單檔案組件模式,即一個組件就是一個檔案,但其實 Vue 也是支持使用 JSX 來撰寫組件的。這里不討論 SFC 和 JSX 的好壞,這個仁者見仁智者見智。本篇文章旨在帶領大家快速了解和使用 Vu ......

    uj5u.com 2023-04-20 08:01:37 more
  • 【Vue2.x原始碼系列06】計算屬性computed原理

    本章目標:計算屬性是如何實作的?計算屬性快取原理以及洋蔥模型的應用?在初始化Vue實體時,我們會給每個計算屬性都創建一個對應watcher,我們稱之為計算屬性watcher ......

    uj5u.com 2023-04-20 08:01:31 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:01:10 more
  • http1.1與http2.0

    一、http是什么 通俗來講,http就是計算機通過網路進行通信的規則,是一個基于請求與回應,無狀態的,應用層協議。常用于TCP/IP協議傳輸資料。目前任何終端之間任何一種通信方式都必須按Http協議進行,否則無法連接。tcp(三次握手,四次揮手)。 請求與回應:客戶端請求、服務端回應資料。 無狀態 ......

    uj5u.com 2023-04-20 08:00:32 more