1. 概述

本教程演示如何在Spring中设置、配置和自定义摘要认证(Digest Authentication)。与之前介绍基本认证的文章类似,我们将基于Spring MVC教程构建,使用Spring Security提供的摘要认证机制来保护应用程序。

2. 安全XML配置

首先要理解的是,虽然Spring Security确实提供了开箱即用的摘要认证机制支持,但这种支持不如基本认证那样完全集成到命名空间中

这种情况下,我们需要手动定义构成安全配置的原始Bean——即DigestAuthenticationFilterDigestAuthenticationEntryPoint

<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集成到整体安全配置中——这里命名空间仍然足够灵活,允许我们这样做:

  1. 第一部分:通过主<http>元素的entry-point-ref属性指向自定义入口点Bean
  2. 第二部分将新定义的摘要过滤器添加到安全过滤器链中。由于此过滤器在功能上等同于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-webspring-security-config作为依赖。

5. 结论

在本教程中,我们通过利用框架中的摘要认证支持,将安全机制引入到简单的Spring MVC项目中。

这些示例的实现可以在Github项目中找到——这是一个基于Eclipse的项目,因此应该易于导入并直接运行。

当项目在本地运行时,可以通过以下地址访问主页html(或通过最小化Tomcat配置在端口80上):

http://localhost:8080/spring-security-mvc-digest-auth/homepage.html

最后,应用程序没有理由在基本认证和摘要认证之间做选择——两者可以同时在相同的URI结构上设置,这样客户端在消费Web应用时可以在两种机制之间自由选择。


原始标题:Spring Security Digest Authentication