一些 Web 頁面只想讓特定的、擁有特定標示的人瀏覽,為了達到這個目標,必不可少的就是認證功能。生活中常見的認證方式包括:賬號密碼驗證、動態令牌、指紋識別、人臉識別、身份證驗證等等。那么,HTTP 常用的認證方式是什么呢?
HTTP 用戶身份認證
BASIC 認證
BASIC 認證(基本認證)是從 HTTP/1.0 就定義的認證方式。即便是現在仍有一部分的網站會使用這種認證方式。是 Web 服務器與通信客戶端之間進行的認證方式。
- 客戶端發出認證請求;
- 服務端接收到請求需要 BASIC 認證,會隨 401 狀態碼 Authorization Required,返回帶 WWW-Authenticate 首部字段的響應。該字段包含認證的方式(BASIC)及 Request-URI 安全域字符串(realm);
- 客戶端接收到服務端的請求后,對用戶名和密碼進行 Base64 編碼處理,發送給服務器;
- 服務端接收到客戶端的請求,對認證信息的正確性進行驗證,驗證通過后,返回一條包含 Request-URI 資源的響應。
需要注意的是,Base64 編碼并非加密處理,因此,BASIC 認證實際是明文傳輸。
DIGEST 認證
- 客戶端發出認證請求;
- 服務器隨著狀態碼 401 Authorization Required,返回帶 WWW-Authenticate 首部字段的響應。該字段內包含認證所需的臨時質詢碼(隨機數,nonce)。
- 客戶端接收到包含 DIGEST 認證必須的首部 Authorization 信息。首部字段 Authorization 內必須包含 username、realm、nonce、uri 和 response 的字段信息。其中,realm 和 nonce 就是之前從服務器接收到的響應中的字段。
- 服務器確認認證信息的正確性,認證通過后則返回包含 Request-URI 資源的響應。并且會在首部字段 Authentication-Info 中寫入一些認證成功的相關信息。
DIGEST 認證提供了高于 BASIC 認證的安全等級,但是和 HTTPS 的客戶端認證相比仍舊很弱。DIGEST 認證提供防止密碼被竊聽的保護機制,但并不存在防止用戶偽裝的保護機制。
SSL 客戶端認證
SSL客戶端認證是借由 HTTPS 的客戶端證書完成認證的方式。憑借客戶端證書認證,服務器可確認訪問是否來自合法的客戶端。SSL 客戶端認證需要事先將客戶端證書分發給客戶端,且客戶端必須安裝此證書。
- 客戶端發出認證請求;
- 服務端接收到需要認證資源的請求,服務器會發送 Certificate Request 報文,要求客戶端提供客戶端證書。
- 用戶選擇將發送的客戶端證書后,客戶端將客戶端證書信息以 Client Certificate 報文方式發送給服務器。
- 服務器驗證客戶端證書,驗證通過后接受證書內客戶端的公開密鑰,開始 HTTPS 加密通信。
SSL 客戶端認證采用雙因素認證,認證過程中不僅需要密碼這一個因素,還需要申請認證者提供其他持有信息,從而作為另一個因素,與其組合使用的認證方式。通過雙因素認證后,就可以確認是用戶本人正在使用匹配正確的計算機訪問服務器。
使用 SSL客戶端認證需要用到客戶端證書。而客戶端證書需要支付一定費用才能使用。每個認證機構頒發客戶端證書的費用不盡相同,平攤到一張證書上,一年費用約幾萬至十幾萬日元。服務器運營者也可以自己搭建認證機構,但要維持安全運行就會產生相應的費用。
基于表單認證
基于表單的認證方法并不是在 HTTP 協議中定義的。客戶端會向服務器上的 Web 應用程序發送登錄信息(Credential),服務器根據登錄信息進行認證。
由于使用上的便利性及安全性問題,HTTP 協議標準提供的 BASIC 認證和 DIGEST 認證幾乎不怎么使用。另外,SSL客戶端認證雖然具有高度的安全等級,但因為導入及維持費用等問題,還尚未普及。
不具備共同標準規范的表單認證,在每個 Web 網站上都會有各不相同的實現方式。如果是全面考慮過安全性能而實現的表單認證,那么就能夠具備高度的安全等級。但在表單認證的實現中存在問題的 Web 網站也是屢見不鮮。
基于表單認證一般會使用 Cookie 來管理 Session(會話):
- 客戶端把用戶 ID 和密碼等登錄信息放入報文的實體部分, 通常是以 POST 方法把請求發送給服務器。而這時,會使用 HTTPS 通信來進行 HTML 表單畫面的顯示和用戶輸入數據的發送。
- 服務器返回用以識別用戶的 Session ID。通過驗證客戶端發送過來的登錄信息,進行身份認證,然后把用戶的認證狀態與 Session ID 綁定后記錄在服務器端。
- 客戶端接收到從服務器端發來的 Session ID 后,會將其作為 Cookie 保存在本地。下次向服務器發送請求時,瀏覽器會自動發送 Cookie,所以 Session ID 也隨之發送到服務器。服務器端可通過驗證接收到的 Session ID 識別用戶和其認證狀態。
除了以上介紹的應用實例,還有應用其他不同方法的案例。另外,不僅基于表單認證的登錄信息及認證過程都無標準化的方法, 服務器端應如何保存用戶提交的密碼等登錄信息等也沒有標準化。通常,一種安全的保存方法是,先利用給密碼加鹽(salt)的方式增加額外信息,再使用散列(hash)函數計算出散列值后保存。但是我們也經常看到直接保存明文密碼的做法,這樣的做法有密碼泄露的風險。
salt 其實就是由服務器隨機生成的一個字符串,但是要保證長度足夠長,并且是真正隨機生成的。然后把它和密碼字符串相連接(前后都可以)生成散列值。當兩個用戶使用了同一個密碼時,由于隨機生成的 salt 值不同,對應的散列值也將是不同的。這樣一來,很大程度上減少了密碼特征,攻擊者也就很難利用自己手中的密碼特征庫進行破解。
最后
我的個人主頁 里也同步進行了更新,歡迎來逛逛。