1. 概述
本教程演示如何在Spring中设置、配置和自定义摘要认证(Digest Authentication)。与之前介绍基本认证的文章类似,我们将基于Spring MVC教程构建,使用Spring Security提供的摘要认证机制来保护应用程序。
2. 安全XML配置
首先要理解的是,虽然Spring Security确实提供了开箱即用的摘要认证机制支持,但这种支持不如基本认证那样完全集成到命名空间中。
这种情况下,我们需要手动定义构成安全配置的原始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集成到整体安全配置中——这里命名空间仍然足够灵活,允许我们这样做:
- 第一部分:通过主
<http>
元素的entry-point-ref
属性指向自定义入口点Bean - 第二部分:将新定义的摘要过滤器添加到安全过滤器链中。由于此过滤器在功能上等同于
BasicAuthenticationFilter
,我们在链中使用相同的相对位置——这通过Spring Security标准过滤器中的BASIC_AUTH_FILTER
别名指定
最后注意,摘要过滤器被配置为指向用户服务Bean——这里命名空间再次派上用场,它允许我们为<user-service>
元素创建的默认用户服务指定Bean名称:
<user-service id="userService">
3. 使用受保护的应用
我们将使用**curl
命令**来消费受保护的应用,并理解客户端如何与之交互。
首先请求主页——不在请求中提供安全凭证:
curl -i http://localhost/spring-security-mvc-digest-auth/homepage.html
不出所料,我们收到带有401 Unauthorized
状态码的响应:
HTTP/1.1 401 Unauthorized
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
命令启用了摘要认证。
服务器的第一个响应将相同——401 Unauthorized
——但现在挑战将被解释并由第二个请求处理——该请求将以200 OK
成功:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=A961E0D...; Path=/spring-security-mvc-digest-auth/; HttpOnly
WWW-Authenticate: Digest realm="Contacts Realm via Digest Authentication", qop="auth",
nonce="MTM3MzYzODgyOTczMTo3YjM4OWQzMGU0YTgwZDg0YmYwZjRlZWJjMDQzZWZkOA=="
Content-Type: text/html;charset=utf-8
Content-Length: 1061
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
头,从而完全避免服务器安全挑战和第二次请求。
4. Maven依赖
安全依赖在Spring Security Maven教程中深入讨论。简而言之,我们需要在pom.xml
中定义spring-security-web
和spring-security-config
作为依赖。
5. 结论
在本教程中,我们通过利用框架中的摘要认证支持,将安全机制引入到简单的Spring MVC项目中。
这些示例的实现可以在Github项目中找到——这是一个基于Eclipse的项目,因此应该易于导入并直接运行。
当项目在本地运行时,可以通过以下地址访问主页html(或通过最小化Tomcat配置在端口80上):
http://localhost:8080/spring-security-mvc-digest-auth/homepage.html
最后,应用程序没有理由在基本认证和摘要认证之间做选择——两者可以同时在相同的URI结构上设置,这样客户端在消费Web应用时可以在两种机制之间自由选择。