springsecurity登录
首先
1.UsernamePasswordAuthenticationFilter->attemptAuthentication (AbstractAuthenticationProcessingFilter 父类 )

successfulAuthentication
 1.1 ProviderManager-> authenticate
 1.1.1 AbstractUserDetailsAuthenticationProvider -> authenticate
   DaoAuthenticationProvider ->retrieveUser UsernamePasswordAuthenticationFilter
 Authentication
 AuthenticationManager
 AuthenticationProvider
 UserDetailsService
 // 回到起点进行后续操作,比如缓存认证信息到session和调用成功后的处理器等等
 UsernamePasswordAuthenticationFilter  接口login在哪定义的?
 public UsernamePasswordAuthenticationFilter() {
     super(new AntPathRequestMatcher("/login", "POST"));
 }
 https://www.jianshu.com/p/a65f883de0c1

-- 第一天

认证总入口
AuthenticationManager -->  ProviderManager 多种认证实现来进行认证,
 依照次序去认证,认证成功则立即返回。
 身份信息的存放容器SecurityContextHolder
 身份信息的抽象Authentication,身份认证器AuthenticationManager及其认证流程

UsernamePasswordAuthenticationFilter->attemptAuthentication (AbstractAuthenticationProcessingFilter 父类 )
 UsernamePasswordAuthenticationFilter 进行封装用户名密码 attemptAuthentication 方法
 ( 用户名 和 密码封装 UsernamePasswordAuthenticationToken)
 AbstractUserDetailsAuthenticationProvider  方法:authenticate 
  是否正确? retrieveUser 方法
  retrieveUser只有第一个参数起主要作用,返回一个UserDetails
 然后将结果进行对比是否正常,操作方法:additionalAuthenticationChecks
 (比对密码的过程,用到了PasswordEncoder和SaltSource,密码加密和盐的概念相信不用我赘述了,它们为保障安全而设计,都是比较基础的概念。)
 iris 将返回的结果进行封装。里面包含了很多相关的其他信息数据 ,在 UserDetailServiceImpl中UserDetails最详细的用户信息,这个接口涵盖了一些必要的用户信息字段,具体的实现类对它进行了扩展。
 public interface UserDetailsService { 
     UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
 }
 Authentication的getCredentials()与UserDetails中的getPassword()需要被区分对待,前者是用户提交的密码凭证,后者是用户正确的密码,认证器其实就是对这两者的比对。  protected void configure(HttpSecurity http) throws Exception {
       http
           .authorizeRequests()
               .antMatchers("/", "/home").permitAll()
               .anyRequest().authenticated()
               .and()
           .formLogin()
               .loginPage("/login")
               .permitAll()
               .and()
           .logout()
               .permitAll();
 }
 除了“/”,”/home”(首页),”/login”(登录),”/logout”(注销),之外,其他路径都需要认证。
 指定“/login”该路径为登录页面,当未认证的用户尝试访问任何受保护的资源时,都会跳转到“/login”。 没有权限。默认跳登陆
 默认指定“/logout”为注销页面 -- 第二天
  @EnableWebSecurity WebSecurityConfiguration-->springSecurityFilterChain 注册了 。
只允许认证用户在同一时间只有一个实例是如何配置的。
  session管理
   @Override
           protected void configure(HttpSecurity http) throws Exception {
               http
                   .authorizeRequests()
                       .anyRequest().hasRole("USER")
                       .and()
                  .formLogin()
                       .permitAll()
                       .and()
                  .sessionManagement()
                       .maximumSessions(1)
                       .expiredUrl("/login?expired");
          }

过滤器链(重要的)
1. SecurityContextPersistenceFilter 两个主要职责:请求来临时,创建SecurityContext安全上下文信息,请求结束时清空SecurityContextHolder。
2.UsernamePasswordAuthenticationFilter 这个会重点分析,表单提交了username和password,被封装成token进行一系列的认证,便是主要通过这个过滤器完成的,在表单认证的方法中,这是最最关键的过滤器。
3.AnonymousAuthenticationFilter 匿名身份过滤器,这个过滤器个人认为很重要,需要将它与UsernamePasswordAuthenticationFilter 放在一起比较理解,spring security为了兼容未登录的访问,也走了一套认证流程,只不过是一个匿名的身份。
4.ExceptionTranslationFilter 直译成异常翻译过滤器,还是比较形象的,这个过滤器本身不处理异常,而是将认证过程中出现的异常交给内部维护的一些类去处理
5.FilterSecurityInterceptor 这个过滤器决定了访问特定路径应该具备的权限,访问的用户的角色,权限是什么?访问的路径需要什么样的角色和权限?
  有了认证,有了请求的封装,有了Session的关联…还缺一个:由什么控制哪些资源是受限的,这些受限的资源需要什么权限,需要什么角色…这一切和访问控制相关的操作,都是由FilterSecurityInterceptor完成的
6. token自定义:==> IpAuthenticationToken extends AbstractAuthenticationToken

oauth2
http://dev.auth.server/oauthserver/oauth/authorize?client_id=oauthclient-system&redirect_uri=http://dev.new.egrant.cn:8081/egrantweb/sp_sec_ck&response_type=code&state=wTOC9V
在请求到达/oauth/token之前经过了ClientCredentialsTokenEndpointFilter这个过滤器
 public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
         throws AuthenticationException, IOException, ServletException {
     ...
     String clientId = request.getParameter("client_id");
     String clientSecret = request.getParameter("client_secret");
  
     ...
     clientId = clientId.trim();
     UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(clientId,
             clientSecret);
  
     return this.getAuthenticationManager().authenticate(authRequest);


 debug可以发现UserDetailsService的实现被适配成了ClientDetailsUserDetailsService,这个设计是将client客户端的信息(client_id,client_secret)适配成用户的信息(username,password),这样我们的认证流程就不需要修改了。
    Token处理端点TokenEndpoint(掌握)
 TokenGranter 来颁发token。其中OAuth2AccessToken的实现类DefaultOAuth2AccessToken就是最终在控制台得到的token序列化之前的原始类: 

tokenGranter的设计思路是使用CompositeTokenGranter管理一个List列表,每一种grantType对应一个具体的真正授权者,在debug过程中可以发现CompositeTokenGranter 内部就是在循环调用五种TokenGranter实现类的grant方法,而granter内部则是通过grantType来区分是否是各自的授权类型。

ResourceOwnerPasswordTokenGranter ==> password密码模式
 AuthorizationCodeTokenGranter ==> authorization_code授权码模式
 ClientCredentialsTokenGranter ==> client_credentials客户端模式
 ImplicitTokenGranter ==> implicit简化模式 
 RefreshTokenGranter ==>refresh_token 刷新token专用 http://localhost:8080/order/1?access_token=950a7cc9-5a8a-42c9-a693-40e817b1a4b0 访问
 进入:
 OAuth2AuthenticationProcessingFilter 
 OAuth2的身份管理器—OAuth2AuthenticationManagerAuthorizationServerTokenServices