如何为 Spring Security 编写认证提供者

jopen 11年前

1. 概述

本教程将会展示如何创建一个Spring Security 的认证提供者,来获得比标准场景下使用的简单的UserDetailsService 更多的灵活性。

2. 认证提供者

Spring Security 对执行认证提供了多样的选择 – 所有选择都基于一个约定 – 即一个 Authentication 请求由一个 AuthenticationProvider 来处理并且返回一个被完全认证的、具有所有凭证的对象。

标准的、最常用的实现是 DaoAuthenticationProvider – 它获取用户详细信息是通过一个简单的只读的用户DAO,UserDetailsService 。当我们想要获取完整的用户实体时,UserDetailsService 却仅能访问用户名 – 然而在大部分情况下,这已经足够了。

更多用户自定义的情境下,为了完成认证过程,将需要访问完整的Authentication 请求 – 例如,当针对一些外部、第三方的服务(比如Crowd)进行认证时  – 来自于认证请求中的 username 和 password  都是必须的。

对这些更高级的场景,我们将需要定义一个自定义的认证提供者:

@Component  public class CustomAuthenticationProvider implements AuthenticationProvider {         @Override      public Authentication authenticate(Authentication authentication) throws AuthenticationException {          String name = authentication.getName();          String password = authentication.getCredentials().toString();             // use the credentials to try to authenticate against the third party system          if (authenticatedAgainstThirdPartySystem()) {              List<GrantedAuthority> grantedAuths = new ArrayList<>();              return new UsernamePasswordAuthenticationToken(name, password, grantedAuths);          } else {              return null;          }      }         @Override      public boolean supports(Class<?> authentication) {          return authentication.equals(UsernamePasswordAuthenticationToken.class);      }     }

注意,返回的Authentication 对象中,授权信息是空的 – 这是因为应用不同,权限信息必然也不同。

3. 安全配置——注册认证提供者

现在认证提供者已经定义好了,我们需要在XML安全配置中指定它,使用可用的命名空间支持:

<?xml version="1.0" encoding="UTF-8"?>  <beans:beans xmlns="http://www.springframework.org/schema/security"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:beans="http://www.springframework.org/schema/beans"      xmlns:sec="http://www.springframework.org/schema/security"      xsi:schemaLocation="        http://www.springframework.org/schema/security        http://www.springframework.org/schema/security/spring-security-3.1.xsd        http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">         <http use-expressions="true">          ...          <http-basic/>      </http>         <authentication-manager>          <authentication-provider ref="customAuthenticationProvider" />      </authentication-manager>     </beans:beans>

4. 认证过程

触发一个认证过程没什么不同的,甚至不用定制认证提供者。我们已经用基本认证建立了我们的安全配置,所以我们可以用一个简单的curl命令来发送一个认证请求:

curl --header "Accept:application/json" -i --user user1:user1Pass      http://localhost:8080/spring-security-custom/api/foo/1
之后我们从服务器获得了期望的200成功结果:
HTTP/1.1 200 OK  Server: Apache-Coyote/1.1  Set-Cookie: JSESSIONID=B8F0EFA81B78DE968088EBB9AFD85A60; Path=/spring-security-custom/; HttpOnly  Content-Type: application/json;charset=UTF-8  Transfer-Encoding: chunked  Date: Sun, 02 Jun 2013 17:50:40 GMT

5. 总结

在这篇文章中我们讨论了一个为Spring安全定制的认证提供者示例。在github项目中可以找到这个实现——这是一个基本的Eclipse项目,所以你可以很轻松的导入和运行它。