一、 瀏覽器與服務器是如何協商使不使用 TLS/SSL 的?
如果你用 HTTP 上知乎,它會返回一個 301,重定向到 HTTPS.
之后瀏覽器就會記住這個網頁支持 HTTPS,在不給出協議 scheme 的情況下(在輸入框只輸入 zhihu.com
),優先使用 HTTPS 訪問。
在 HTTPS 協議中,先建立 TCP 連接,然后在建立 TLS/SSL 連接前,會有一個加密方法協商,在其中瀏覽器和服務器協商具體的加密協議版本。
二、 瀏覽器與服務器是如何協商用哪個版本的 HTTP 的?
在 HTTPS 通信中,之前說過連接建立前會有一個加密方法協商的步驟。為了支持 HTTP/2,在該協商步驟中加入了 ALPN(Application Layer Protocol Negotiation,應用層協議協商)的拓展。
客戶端在建立 TLS/SSL 連接的 Client Hello 握手中,會通過 ALPN 拓展列出自己支持的各種應用層協議。然后服務端可以按需從中選擇,並在 Server Hello 中指定具體要使用的協議。
而在 HTTP 通信或者不支持 ALPN 的 HTTPS 通信中,可以通過 Connection: Upgrade
方式從 HTTP/1.x 升級到 HTTP/2.在 HTTP Upgrade 機制中,HTTP/2 的協議名稱是 h2c
:
GET / HTTP/1.1
Host: example.com
Connection: Upgrade, HTTP2-Settings
Upgrade: h2c
HTTP2-Settings: <base64url encoding of HTTP/2 SETTINGS payload>
如果服務端不支持 HTTP/2,它會直接返回 HTTP/1 的響應。否則就返回 101 switching.
HTTP/1.0
就服務器而言,即使它收到的是 HTTP/1.0 的請求,也會返回 HTTP/1.1 的響應。這也算是一種協商機制:服務器通過 HTTP/1.1 的響應通知客戶端,我是支持 HTTP/1.1 的。
因為 HTTP/1.0 和 HTTP/1.1 都是文本格式的協議,是兼容的,因此可以這樣返回。但是 HTTP/2 是二進制協議,不兼容,就必須通過 ALPN 或 Upgrade 協商。