Spring Security认证流程源码

     Spring Security框架大体实现:首先在初始化Spring Security时,会创建一个类型为FilterChainProxy,名为 SpringSecurityFilterChain 的Servlet过滤器,这个过滤器只是一个代理,工作的是类型为SecurityFilterChain过滤器链,负责认证的过滤器会调用认证接口AuthenticationManager;负责授权的过滤器会调用授权接口AccessDecisionManager。

        

    先看一个流程图:

  

UsernamePasswordAuthenticationFilter

  

   进入UsernamePasswordAuthenticationFilter的方法中,第二个红色方框中的username和password是前端传递的用户名和密码。然后包装为UsernamePasswordAuthenticationToken,这个类实现Authentication接口!包装完成之后调用getAuthenticationManager().authenticate(authRequest)。AuthenticationManager有很多实现类,其中一个就是ProvideManager。将各种认证方式集成到List<AuthenticationProvider> 列表 ,每种认证方式都会实现 AuthenticationProvider接口,其中authenticate()方法定义了认证的实现过程,supports()方法定义支持那种认证类型,认证成功后会返回AuthenticationToken

public interface AuthenticationProvider {
    Authentication authenticate(Authentication authentication) throws AuthenticationException;
    boolean supports(Class<?> var1);
}

ProvideManager

  选择provider

  

   ProvideManager负责管理AuthenticationProvider,可以看到图中有很多的providers,可以有SocialAuthenticationProvider(第三方接入的时候专用),AbstractUserDetailsAuthenticationProvider(配置的时候用到的)等等。其实真正执行的只有一个provider,那么究竟会选择哪一个provider,看到有一个supports方法。也就是根据上一步中的authentication的类型来做判断。

调用provider的authenticate方法

         获取用户信息

  

   关键方法就是调用我们自己实现的UserDetailsService类的方法先把用户获取到

检查获取到的用户信息

验证密码是否正确

验证密码是否过期

创建UsernamePasswordAuthenticationToken表示认证成功

SecurityContextPersistenceFilter

  把用户信息认证完了后,其他请求是如何共享这一次登录验证的呢?这个就是靠SecurityContext上下文来完成这项工作的。用户认证完成之后会把UsernamePasswordAuthenticationToken存入到Context中,而Context会存储到session当中去,这样,下一次请求过来的时候,就不用让用户在登录了。那么是谁把认证信息放到Context里面去的呢?答案就是SecurityContextPersistenceFilter,这个Filter处于所有Filter的最前端位置:

  
       SecurityContextPersistenceFilter 这个Filter是整个拦截过程的入口和出口(也就是第一个和最后一个拦截器),会在请求开始时从配置好的 SecurityContextRepository 中获取 SecurityContext,然后把它设置给SecurityContextHolder。在请求完成后将 SecurityContextHolder 持有的 SecurityContext 再保存到配置好的 SecurityContextRepository,同时清除 securityContextHolder 所持有的 SecurityContext;
  UsernamePasswordAuthenticationFilter 用于处理来自表单提交的认证。该表单必须提供对应的用户名和密码,其内部还有登录成功或失败后进行处理的 AuthenticationSuccessHandler 和AuthenticationFailureHandler,这些都可以根据需求做相关改变
  FilterSecurityInterceptor 是用于保护web资源的,使用AccessDecisionManager对当前用户进行授权访问;
  ExceptionTranslationFilter 能够捕获来自 FilterChain 所有的异常,并进行处理。但是它只会处理两类异常:AuthenticationException 和 AccessDeniedException,其它的异常它会继续抛出。

  

授权过程

       FilterSecurityInterceptor会调用AccessDecisionManager进行授权决策,若决策通过,则允许访问资源,否则将禁止访问,AccessDecisionManager采用投票的方式来确定是否能够访问受保护资源。

public interface AccessDecisionManager {
    //decide接口就是用来鉴定当前用户是否有访问对应受保护资源的权限。
    void decide(Authentication authentication , Object object, ...) ;    
}

  权限信息保存在SecurityMetadataSource的子类中

antMatchers("/xx/").hasAuthority("X") antMatchers("/yy/").hasAuthority("Y")

  

   

  

 

  
posted on 2020-02-24 15:11  溪水静幽  阅读(197)  评论(0)    收藏  举报