聊聊SpringSecurity认证流程和授权流程

举报
周杰伦本人 发表于 2022/09/29 13:24:18 2022/09/29
【摘要】 聊聊SpringSecurity认证流程和授权流程 认证流程我们先聊一下SpringSecurity的认证流程首先是AbstractAuthenticationProcessingFilter的doFilter()方法public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) t...

聊聊SpringSecurity认证流程和授权流程

认证流程

我们先聊一下SpringSecurity的认证流程

首先是AbstractAuthenticationProcessingFilter的doFilter()方法

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
      throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    if (!requiresAuthentication(request, response)) {
      chain.doFilter(request, response);

      return;
    }


    Authentication authResult;

    try {
      authResult = attemptAuthentication(request, response);
      if (authResult == null) {
        
        return;
      }
      sessionStrategy.onAuthentication(authResult, request, response);
    }
    catch (InternalAuthenticationServiceException failed) {
      logger.error(
          "An internal error occurred while trying to authenticate the user.",
          failed);
      unsuccessfulAuthentication(request, response, failed);

      return;
    }
    catch (AuthenticationException failed) {
      // Authentication failed
      unsuccessfulAuthentication(request, response, failed);

      return;
    }

    // Authentication success
    if (continueChainBeforeSuccessfulAuthentication) {
      chain.doFilter(request, response);
    }

    successfulAuthentication(request, response, chain, authResult);
  }

attemptAuthentication()

方法中调用抽象方法attemptAuthentication()获取认证信息,实现类是UsernamePasswordAuthenticationFilter,它的attemptAuthentication()方法:

  1. 获取用户和密码
  2. 创建UsernamePasswordAuthenticationToken对象,认证结果暂时设置为false
  3. 调用getAuthenticationManager()方法获取认证管理器ProviderManager
  4. 调用authenticate()方法

ProviderManager的authenticate()方法中获取所有的AuthenticationProvider实例,遍历看哪个,最终找到AbstractUserDetailsAuthenticationProvider的supports()方法,发现支持UsernamePasswordAuthenticationToken,发现支持后调用AbstractUserDetailsAuthenticationProvider的authenticate()方法,方法中根据用户名查找缓存有没有,没有的话调用retrieveUser()方法,方法中调用

this.getUserDetailsService().loadUserByUsername(username);也就是实现UserDetailsService接口的自定义类loadUserByUsername()方法,获取用户信息和权限信息封装到UserDetails中并返回

继续看AbstractUserDetailsAuthenticationProvider的authenticate()方法,获取完UserDetails信息后进行预检查,看一下用户是否被冻结等等,然后进入DaoAuthenticationProvider的additionalAuthenticationChecks(),这个方法里进行密码的比对,看数据库的密码和表单密码是否一致,默认比对逻辑是BCryptPasswordEncoder的matches()方法完成的

然后是AbstractUserDetailsAuthenticationProvider的postAuthenticationChecks.check(user);进行后置检查,检查账户是否过期等,

然后调用createSuccessAuthentication()方法,创建UsernamePasswordAuthenticationToken对象,构造方法中设置authenticated为true,表示已经通过认证,返回UsernamePasswordAuthenticationToken对象

至此attemptAuthentication()

successfulAuthentication()

AbstractAuthenticationProcessingFilter的successfulAuthentication()方法中把认证信息写入SecurityContextHolder.getContext()中,然后调用AuthenticationSuccessHandler的onAuthenticationSuccess方法,我们可以实现AuthenticationSuccessHandler接口自定义认证成功的处理类

unsuccessfulAuthentication()

失败方法是unsuccessfulAuthentication(),方法中清空SecurityContextHolder保存的信息,调用AuthenticationFailureHandler的onAuthenticationFailure(),我们同样可以实现AuthenticationFailureHandler接口自定义认证失败处理类

授权流程

认证涉及到的过滤器为FilterSecurityInterceptor

  • 调用invoke方法,

    • 进入AbstractSecurityInterceptor的beforeInvocation()方法:

      通过obtainSecurityMetadataSource()获取系统中的权限的配置

      • 进入authenticateIfRequired()方法

        获取Authentication信息,这里面有用户的权限列表,并返回

      • 得到认证信息后调用AccessDecisionManager决策管理器的decide()方法

        方法中获取投票者进行投票

        如果投票不通过的话会抛出AccessDeniedException异常,被ExceptionTranslationFilter处理

总结

我们主要讲了一下SpringSecurity的表单认证流程和授权流程,主要是AbstractAuthenticationProcessingFilter过滤器的作用,我们对AbstractAuthenticationProcessingFilter进行代码分析,涉及过滤器UsernamePasswordAuthenticationFilter,并对其中的方法进行了分析,以及认证成功和认证失败的处理方法successfulAuthentication()和unsuccessfulAuthentication()进行了分析。授权流程主要涉及的是FilterSecurityInterceptor类,通过投票决策器进行投票来判断是否有相应的权限

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。