天天看點

圖解HTTP八:确認通路使用者身份的認證

8.1 何為認證

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

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

8.2 BASIC 認證

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

圖解HTTP八:确認通路使用者身份的認證
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 編碼的轉換工作。

圖解HTTP八:确認通路使用者身份的認證

步驟 3: 接收到包含首部字段 Authorization 請求的伺服器,會對認證資訊的正确性進行驗證。如驗證通過,則傳回一條包含 Request-URI 資源的響應。BASIC 認證雖然采用 Base64 編碼方式,但這不是加密處理。不需要任何附加資訊即可對其解碼。換言之,由于明文解碼後就是使用者 ID 和密碼,在 HTTP 等非加密通信的線路上進行 BASIC 認證的過程中,如果被人竊聽,被盜的可能性極高。另外,除此之外想再進行一次 BASIC 認證時,一般的浏覽器卻無法實作認證登出操作,這也是問題之一。

BASIC 認證使用上不夠便捷靈活,且達不到多數 Web 網站期望的安全性等級,是以它并不常用。

8.3 DIGEST 認證

DIGEST 認證同樣使用質詢 / 響應的方式(challenge/response),但不會像 BASIC 認證那樣直接發送明文密碼。所謂質詢響應方式是指,一開始一方會先發送認證要求給另一方,接着使用從另一方那接收到的質詢碼計算生成響應碼。最後将響應碼傳回給對方進行認證的方式。

圖解HTTP八:确認通路使用者身份的認證

因為發送給對方的隻是響應摘要及由質詢碼産生的計算結果,是以比起 BASIC 認證,密碼洩露的可能性就降低了。

圖解HTTP八:确認通路使用者身份的認證
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),按登入資訊的驗證結果認證。

圖解HTTP八:确認通路使用者身份的認證
基于表單認證示例( Google)

多數情況下,輸入已事先登入的使用者 ID(通常是任意字元串或郵件位址)和密碼等登入資訊後,發送給 Web應用程式,基于認證結果來決定認證是否成功。

8.5.1 認證多半為基于表單認證

Web 應用程式各自實作基于表單的認證方式。

8.5.2 Session 管理及 Cookie 應用

基于表單認證本身是通過伺服器端的 Web 應用,将用戶端發送過來的使用者 ID 和密碼與之前登入過的資訊做比對來進行認證的。但鑒于 HTTP 是無狀态協定,之前已認證成功的使用者狀态無法通過協定層面儲存下來。即,無法實作狀态管理,是以即使當該使用者下一次繼續通路,也無法區分他與其他的使用者。于是我們會使用 Cookie 來管理 Session,以彌補 HTTP 協定中不存在的狀态管理功能。

圖解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)函數計算出散列值後儲存。但是我們也經常看到直接儲存明文密碼的做法,而這樣的做法具有導緻密碼洩露的風險。

繼續閱讀