1. 概述
本教程演示瞭如何設置、配置和自定義使用 Spring 的 Digest 身份驗證。類似於之前介紹 Basic 身份驗證的文章,我們將在此基礎上構建,並使用 Spring Security 提供的 Digest 身份驗證機制來保護應用程序。Digest 身份驗證 是 Basic 身份驗證的改進,旨在通過確保憑據在網絡上傳輸時不使用明文,來解決先前身份驗證機制中的問題。
2. Digest XML 配置
理解配置的關鍵在於,雖然 Spring Security 已經提供了 Digest 認證機制的全支持,但這種支持與 Basic 認證相比,在命名空間中的集成程度並不高。
在這種情況下,我們需要手動定義構成安全配置的原始 Bean – DigestAuthenticationFilter 和 DigestAuthenticationEntryPoint:
<beans:bean id="digestFilter"
class="org.springframework.security.web.authentication.www.DigestAuthenticationFilter">
<beans:property name="userDetailsService" ref="userService" />
<beans:property name="authenticationEntryPoint" ref="digestEntryPoint" />
</beans:bean>
<beans:bean id="digestEntryPoint"
class="org.springframework.security.web.authentication.www.DigestAuthenticationEntryPoint">
<beans:property name="realmName" value="Contacts Realm via Digest Authentication" />
<beans:property name="key" value="acegi" />
</beans:bean>
<!-- 安全命名空間配置 -->
<http use-expressions="true" entry-point-ref="digestEntryPoint">
<intercept-url pattern="/**" access="isAuthenticated()" />
<custom-filter ref="digestFilter" after="BASIC_AUTH_FILTER" />
</http>
<authentication-manager>
<authentication-provider>
<user-service id="userService">
<user name="user1" password="user1Pass" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
接下來,我們需要將這些 Bean 集成到整體安全配置中 – 在這種情況下,命名空間仍然足夠靈活,允許我們做到這一點。
第一部分是指向自定義入口點 Bean,通過 entry-point-ref 屬性,在主 <http> 元素中。
第二部分是 將新定義的 Digest 過濾器添加到安全過濾器鏈中。 由於此過濾器在功能上與 BasicAuthenticationFilter 相同,因此我們使用相同的相對位置在鏈中 – 這一點由 BASIC_AUTH_FILTER 別名在整體中指定。
最後,請注意,Digest 過濾器配置為 指向用户服務 Bean – 在這裏,命名空間再次非常有用,因為它允許我們為 <user-service> 元素創建的默認用户服務指定 Bean 名稱:
<user-service id="userService">
3. 消耗受保護的應用程序
我們將使用 curl 命令來消耗受保護的應用程序,並瞭解客户端如何與之交互。
讓我們首先請求主頁 – 而無需在請求中提供安全憑據:
curl -i http://localhost/spring-security-mvc-digest-auth/homepage.html
正如預期的那樣,我們收到了一條包含 401 未授權 狀態碼的響應:
HTTP/1.1 401 未授權
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=CF0233C...; Path=/spring-security-mvc-digest-auth/; HttpOnly
WWW-Authenticate: Digest realm="Contacts Realm via Digest Authentication", qop="auth",
nonce="MTM3MzYzODE2NTg3OTo3MmYxN2JkOWYxZTc4MzdmMzBiN2Q0YmY0ZTU0N2RkZg=="
Content-Type: text/html;charset=utf-8
Content-Length: 1061
Date: Fri, 12 Jul 2013 14:04:25 GMT
如果此請求由瀏覽器發送,則身份驗證挑戰將提示用户使用簡單的用户/密碼對話框輸入憑據。
現在,讓我們 提供正確的憑據 並再次發送請求:
curl -i --digest --user
user1:user1Pass http://localhost/spring-security-mvc-digest-auth/homepage.html
請注意,我們已通過 –digest 標誌啓用了 curl 命令中的 Digest 身份驗證。
服務器的第一次響應將與 401 未授權 相同 – 但挑戰將現在被第二次請求解釋並處理 – 從而成功,狀態碼為 200 OK:
HTTP/1.1 401 未授權
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=A961E0D...; Path=/spring-security-mvc-digest-auth/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Content-Length: 90
Date: Fri, 12 Jul 2013 14:15:29 GMT
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=55F996B...; Path=/spring-security-mvc-digest-auth/; HttpOnly
Content-Type: text/html;charset=ISO-8859-1
Content-Language: en-US
Content-Length: 90
Date: Fri, 12 Jul 2013 14:15:29 GMT
<html>
<head></head>
<body>
<h1>This is the homepage</h1>
</body>
</html>
關於此交互的最後一條注意事項是,客户端可以 在第一次請求中主動發送正確的 Authorization 標頭,從而完全避免服務器身份驗證挑戰和第二次請求。
解釋響應的一些參數:
- realm: 定義了用於 Web 或應用程序服務器的安全性策略域。受保護的資源可以在服務器上劃分為一組保護空間,每個保護空間都有其自己的身份驗證方案和/或授權數據庫,其中包含用户和組的集合。
- nonce: 是一種替代機制,用於白名單源,它是一個服務器在每次頁面請求中生成的唯一隨機字符串。通過使用此屬性,您可以僅允許具有正確值的內聯腳本或樣式執行,從而使攻擊者能夠以一種困難的方式攻擊。
- qop: 質量保證,可以設置為“auth”。
4. Maven 依賴項
安全依賴項在 Spring Security Maven 教程中進行了深入討論。簡而言之,我們需要在我們的 pom.xml 中定義 spring-security-web 和 spring-security-config 作為依賴項。5. 結論
在本教程中,我們通過利用框架中的 Digest Authentication 支持,將安全性引入了一個簡單的 Spring MVC 項目。
當項目在本地運行時,主頁 HTML 可在以下地址訪問(或,通過最小的 Tomcat 配置,在端口 8080 上):
http://localhost:8080/spring-security-mvc-digest-auth/homepage.html
實際上,應用程序無需選擇 Basic 和 Digest 認證之間 – 兩者都可以同時配置在相同的 URI 結構上,以這種方式,客户端可以在消費 Web 應用程序時選擇使用兩種機制。