圖解HTTP八:確認訪問用戶身份的認證

8.1 何爲認證

HTTP/1.1 使用的認證方式如下所示。

  • BASIC 認證(基本認證)
  • DIGEST 認證(摘要認證)
  • SSL 客戶端認證
  • FormBase 認證(基於表單認證)

8.2 BASIC 認證

BASIC 認證(基本認證)是從 HTTP/1.0 就定義的認證方式。即便是現在仍有一部分的網站會使用這種認證方式。是 Web 服務器與通信客戶端之間進行的認證方式。
在這裏插入圖片描述

BASIC 認證概要

  • 步驟 1: 當請求的資源需要 BASIC 認證時,服務器會隨狀態碼 401 Authorization Required,返回帶 WWWAuthenticate 首部字段的響應。該字段內包含認證的方式(BASIC) 及 Request-URI 安全域字符串(realm)。
  • 步驟 2: 接收到狀態碼 401 的客戶端爲了通過 BASIC 認證,需要將用戶 ID 及密碼發送給服務器。發送的字符串內容是由用戶 ID 和密碼構成,兩者中間以冒號(:)連接後,再經過 Base64 編碼處理。

假設用戶 ID 爲 guest,密碼是 guest,連接起來就會形成 guest:guest 這樣的字符串。然後經過 Base64 編碼,最後的結果即是 Z3Vlc3Q6Z3Vlc3Q=。把這串字符串寫入首部字段 Authorization 後,發送請求。

當用戶代理爲瀏覽器時,用戶僅需輸入用戶 ID 和密碼即可,之後,瀏覽器會自動完成到 Base64 編碼的轉換工作。

在這裏插入圖片描述
步驟 3: 接收到包含首部字段 Authorization 請求的服務器,會對認證信息的正確性進行驗證。如驗證通過,則返回一條包含 Request-URI 資源的響應。BASIC 認證雖然採用 Base64 編碼方式,但這不是加密處理。不需要任何附加信息即可對其解碼。換言之,由於明文解碼後就是用戶 ID 和密碼,在 HTTP 等非加密通信的線路上進行 BASIC 認證的過程中,如果被人竊聽,被盜的可能性極高。另外,除此之外想再進行一次 BASIC 認證時,一般的瀏覽器卻無法實現認證註銷操作,這也是問題之一。
BASIC 認證使用上不夠便捷靈活,且達不到多數 Web 網站期望的安全性等級,因此它並不常用。

8.3 DIGEST 認證

DIGEST 認證同樣使用質詢 / 響應的方式(challenge/response),但不會像 BASIC 認證那樣直接發送明文密碼。所謂質詢響應方式是指,一開始一方會先發送認證要求給另一方,接着使用從另一方那接收到的質詢碼計算生成響應碼。最後將響應碼返回給對方進行認證的方式。
在這裏插入圖片描述
因爲發送給對方的只是響應摘要及由質詢碼產生的計算結果,所以比起 BASIC 認證,密碼泄露的可能性就降低了。
在這裏插入圖片描述

DIGEST 認證概要

  • 步驟 1: 請求需認證的資源時,服務器會隨着狀態碼 401 Authorization Required,返回帶WWWAuthenticate 首部字段的響應。該字段內包含質問響應方式認證所需的臨時質詢碼(隨機數, nonce)。首部字段 WWW-Authenticate 內必須包含 realm 和 nonce 這兩個字段的信息。客戶端就是依靠向服務器回送這兩個值進行認證的。nonce 是一種每次隨返回的 401 響應生成的任意隨機字符串。該字符串通常推薦由 Base64 編碼的十六進制數的組成形式,但實際內容依賴服務器的具體實現。
  • 步驟 2: 接收到 401 狀態碼的客戶端,返回的響應中包含 DIGEST 認證必須的首部字段 Authorization 信息。首部字段 Authorization 內必須包含 username、 realm、 nonce、 uri 和 response 的字段信息。其中, realm 和 nonce 就是之前從服務器接收到的響應中的字段。username 是 realm 限定範圍內可進行認證的用戶名。uri(digest-uri)即 Request-URI 的值,但考慮到經代理轉發後 Request-URI 的值可能被修改,因此事先會複製一份副本保存在 uri 內。response 也可叫做 Request-Digest,存放經過 MD5 運算後的密碼字符串,形成響應碼。響應中其他的實體請參見第 6 章的請求首部字段 Authorization。另外,有關 Request-Digest 的計算規則較複雜,有興趣的讀者不妨深入學習一下 RFC2617。
  • 步驟 3: 接收到包含首部字段 Authorization 請求的服務器,會確認認證信息的正確性。認證通過後則返回包含 Request-URI 資源的響應。並且這時會在首部字段 Authentication-Info 寫入一些認證成功的相關信息。DIGEST 認證提供了高於 BASIC 認證的安全等級,但是和 HTTPS 的客戶端認證相比仍舊很弱。 DIGEST 認證提供防止密碼被竊聽的保護機制,但並不存在防止用戶僞裝的保護機制。DIGEST 認證和 BASIC 認證一樣,使用上不那麼便捷靈活,且仍達不到多數 Web 網站對高度安全等級的追求標準。因此它的適用範圍也有所受限。

8.4 SSL 客戶端認證

從使用用戶 ID 和密碼的認證方式方面來講,只要二者的內容正確,即可認證是本人的行爲。但如果用戶 ID和密碼被盜,就很有可能被第三者冒充。利用 SSL 客戶端認證則可以避免該情況的發生。SSL 客戶端認證是藉由 HTTPS 的客戶端證書完成認證的方式。憑藉客戶端證書(在 HTTPS 一章已講解)認證,服務器可確認訪問是否來自已登錄的客戶端。

8.4.1 SSL 客戶端認證的認證步驟

  • 步驟 1: 接收到需要認證資源的請求,服務器會發送 Certificate Request 報文,要求客戶端提供客戶端證書。
  • 步驟 2: 用戶選擇將發送的客戶端證書後,客戶端會把客戶端證書信息以 Client Certificate 報文方式發送給服務器。
  • 步驟 3: 服務器驗證客戶端證書驗證通過後方可領取證書內客戶端的公開密鑰,然後開始 HTTPS 加密通信。

8.4.2 SSL 客戶端認證採用雙因素認證

在多數情況下, SSL 客戶端認證不會僅依靠證書完成認證,一般會和基於表單認證(稍後講解)組合形成一種雙因素認證(Two-factor authentication)來使用。所謂雙因素認證就是指,認證過程中不僅需要密碼這一個因素,還需要申請認證者提供其他持有信息,從而作爲另一個因素,與其組合使用的認證方式。換言之,第一個認證因素的 SSL 客戶端證書用來認證客戶端計算機,另一個認證因素的密碼則用來確定這是用戶本人的行爲。通過雙因素認證後,就可以確認是用戶本人正在使用匹配正確的計算機訪問服務器。

8.5 基於表單認證

基於表單的認證方法並不是在 HTTP 協議中定義的。客戶端會向服務器上的 Web 應用程序發送登錄信息(Credential),按登錄信息的驗證結果認證。

基於表單認證示例( Google)

多數情況下,輸入已事先登錄的用戶 ID(通常是任意字符串或郵件地址)和密碼等登錄信息後,發送給 Web應用程序,基於認證結果來決定認證是否成功。

8.5.1 認證多半爲基於表單認證

Web 應用程序各自實現基於表單的認證方式。

8.5.2 Session 管理及 Cookie 應用

基於表單認證本身是通過服務器端的 Web 應用,將客戶端發送過來的用戶 ID 和密碼與之前登錄過的信息做匹配來進行認證的。但鑑於 HTTP 是無狀態協議,之前已認證成功的用戶狀態無法通過協議層面保存下來。即,無法實現狀態管理,因此即使當該用戶下一次繼續訪問,也無法區分他與其他的用戶。於是我們會使用 Cookie 來管理 Session,以彌補 HTTP 協議中不存在的狀態管理功能。
在這裏插入圖片描述

Session 管理及 Cookie 狀態管理

  • 步驟 1: 客戶端把用戶 ID 和密碼等登錄信息放入報文的實體部分,通常是以 POST 方法把請求發送給服務器。而這時,會使用 HTTPS 通信來進行 HTML 表單畫面的顯示和用戶輸入數據的發送。
  • 步驟 2: 服務器會發放用以識別用戶的 Session ID。通過驗證從客戶端發送過來的登錄信息進行身份認證,然後把用戶的認證狀態與 Session ID 綁定後記錄在服務器端。向客戶端返回響應時,會在首部字段 Set-Cookie 內寫入 Session ID(如 PHPSESSID=028a8c…)。你可以把 Session ID 想象成一種用以區分不同用戶的等位號。然而,如果 Session ID 被第三方盜走,對方就可以僞裝成你的身份進行惡意操作了。因此必須防止 SessionID 被盜,或被猜出。爲了做到這點, Session ID 應使用難以推測的字符串,且服務器端也需要進行有效期的管理,保證其安全性。另外,爲減輕跨站腳本攻擊(XSS)造成的損失,建議事先在 Cookie 內加上 httponly 屬性。
  • 步驟 3: 客戶端接收到從服務器端發來的 Session ID 後,會將其作爲 Cookie 保存在本地。下次向服務器發送請求時,瀏覽器會自動發送 Cookie,所以 Session ID 也隨之發送到服務器。服務器端可通過驗證接收到的 Session ID 識別用戶和其認證狀態。

通常,一種安全的保存方法是,先利用給密碼加鹽(salt) 1 的方式增加額外信息,再使用散列(hash)函數計算出散列值後保存。但是我們也經常看到直接保存明文密碼的做法,而這樣的做法具有導致密碼泄露的風險。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章