在大多数情况下,当仅使用用户名和密码进行身份验证和角色进行授权时,实现自己的 UserDetailsService 就足够了。
那么用户名密码认证的流程一般如下:
- 一个 spring 安全过滤器(基本身份验证/表单/..)获取用户名和密码,将其转换为 UsernamePasswordAuthentication 对象并将其传递给 AuthenticationManager
- 身份验证管理器寻找可以处理 UsernamePasswordtokens 的候选提供者,在这种情况下是 DaoAuthenticationProvider 并传递令牌以进行身份验证
- 身份验证提供程序调用方法 loadUserByUsername 接口并在用户不存在时抛出 UsernameNotFound 异常或返回包含用户名、密码和权限的 UserDetails 对象。
- 然后,身份验证提供程序比较提供的 UsernamePasswordToken 和 UserDetails 对象的密码。(它还可以通过 PasswordEncoders 处理密码哈希)如果不匹配,则身份验证失败。如果匹配,则注册用户详细信息对象并将其传递给 AccessDecisionManager,后者执行授权部分。
因此,如果 DaoAuthenticationProvider 中的验证符合您的需求。然后你只需要实现你自己的 UserDetailsService 并调整 DaoAuthenticationProvider 的验证。
使用 spring 3.1 的 UserDetailsService 示例如下:
春天 XML:
<security:authentication-manager>
<security:authentication-provider user-service-ref="myUserDetailsService" />
</security:authentication-manager>
<bean name="myUserDetailsService" class="x.y.MyUserDetailsService" />
UserDetailsService 实现:
public MyUserDetailsService implements UserDetailsService {
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//Retrieve the user from wherever you store it, e.g. a database
MyUserClass user = ...;
if (user == null) {
throw new UsernameNotFoundException("Invalid username/password.");
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("Role1","role2","role3");
return new User(user.getUsername(), user.getPassword(), authorities);
}
}