spring security3这本书中、有这样的一个图,很形象的描绘出了一个用户的认证过程,如下:
用户发送一个请求,这时候被一个过滤器拦截(AbstractAuthenticationProcessingFilter),拦截以后将请求信息分装成一个包含凭证信息的一个Authentication对象,然后将此对象交给认证管理器(AtuthenticationManager)进行操作,AuthenticationManager将这个凭证信息交给认证管理者(AuthenticationProvider)进行操作,AuthenticationProvider在"凭证库"(Authentication Credential Storage)中进行对比,如果未成功,那么抛出认证异常信息,如果成功,将凭证信息重新封装成Authentication对象,并且赋予它相应的权限(授权),将请求继续,用户验证成功!
这个图很完美的表现除了验证的一个过程。
从这个图中,也可以看出来,认证大概从3个方面下手的:
1.AbstractAuthenticationProcessingFilter (这是符合spring security设计的一个过滤器,我们通过这个入口才可以进行认证等操作)
2.AuthenticationManager (这个只是一个管理者,它应该负责把认证信息交给哪个Provider去操作)
3.AuthenticationProvider(其实这个是主要"做事"的,它去完成了认证决策等操作)
在上边的图上,我们注意一点,当认证成功后,返回的是一个分装后的Authentication对象,那么这个对象是不是封装了相关的用户信息呢,。看一下eclipse中Authentication中的Outline:
很明显有6个方法:
Object getPrincipal() 返回安全实体的唯一标识(如,一个用户名)
Object getCredentials() 返回安全实体的凭证信息
List<GrantedAuthority> getAuthorities() 得到安全实体的权限集合,根据认证信息的存储决定的。
Object getDetails() 返回一个跟认证提供者相关的安全实体细节信息
boolean isAuthenticated () 是否认证成功
void setAuthenticated(boolean paramBoolean) throws IllegalArgumentException; 设置认证状态
看一看,Authentication对象是很有意思的。 呵呵
书中说:"Spring Security 只提供了AuthenticationManager 的一个具体实现类,即o.s.s.authentication.ProviderManager,它会使用一个或更多以上描述的AuthenticationProvider实现类。因为AuthenticationProvider的使用非常普遍并且被很好的集成在ProviderManager中,所以理解它在最常见的基本配置下是如何工作的就非常重要了."
从这段话中我们可以得知,AuthenticationManager是通过ProviderMager这个实现类去和AuthenticationProvider去沟通的,而且还可以得知,AUthenticationProvider可以配置多个。
我又查看了spring security提供给我们的文档。
里边有一个比较有意思的例子、 我们可以试着分析一下验证流程,如下:
- import org.springframework.security.authentication.*;
- import org.springframework.security.core.*;
- import org.springframework.security.core.authority.SimpleGrantedAuthority;
- import org.springframework.security.core.context.SecurityContextHolder;
- public class AuthenticationExample {
- private static AuthenticationManager am = new SampleAuthenticationManager();
- public static void main(String[] args) throws Exception {
- BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
- while(true) {
- System.out.println("Please enter your username:");
- String name = in.readLine();
- System.out.println("Please enter your password:");
- String password = in.readLine();
- try {
- Authentication request = new UsernamePasswordAuthenticationToken(name, password);
- Authentication result = am.authenticate(request);
- SecurityContextHolder.getContext().setAuthentication(result);
- break;
- } catch(AuthenticationException e) {
- System.out.println("Authentication failed: " + e.getMessage());
- }
- }
- System.out.println("Successfully authenticated. Security context contains: " +
- SecurityContextHolder.getContext().getAuthentication());
- }
- }
- class SampleAuthenticationManager implements AuthenticationManager {
- static final List<GrantedAuthority> AUTHORITIES = new ArrayList<GrantedAuthority>();
- static {
- AUTHORITIES.add(new SimpleGrantedAuthority("ROLE_USER"));
- }
- public Authentication authenticate(Authentication auth) throws AuthenticationException {
- if (auth.getName().equals(auth.getCredentials())) {
- return new UsernamePasswordAuthenticationToken(auth.getName(),
- auth.getCredentials(), AUTHORITIES);
- }
- throw new BadCredentialsException("Bad Credentials");
- }
- }
咱们仔细研究一下这个例子,会发现,这个简单的例子正是最上面那个图的流程,。
1.首先用户发起请求:
通过输入用户名和密码
System.out.println("Please enter your username:");
String name = in.readLine();
System.out.println("Please enter your password:");
String password = in.readLine();
2.然后将凭证信息封装成Authentication对象
Authentication request = new UsernamePasswordAuthenticationToken(name, password);
UsernamePasswordAuthenticationToken对象的父类其实也是Authentication,这里用了一个多态的机制。
3.将封装好的认证对象(Authentication request)交给认证管理器管理
Authentication result = am.authenticate(request);
4.认证管理器交给认证管理者处理(这里 他没有使用AuthenticationProvider ,可能因为例子太简单,没有必要吧, 呵呵)
5.认证管理器如果通过 那么授权封装用户信息,然后返回封装后的Authentication对象,否则。抛出异常
好吧。通过这次的学习,就可以掌握spring security整个认证管理的过程了。