SpringSecurity登录的基本流程

SpringSecurity

SpringSecurity的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器.这里我们可以看看入门案例的过滤器

在这里插入图片描述
在这里插入图片描述
基本组件讲解:

AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter 是 Spring Security框架中的一个类,它提供了一个用于处理身份验证请求的基本实现。 当客户端向服务器发送身份验证请求时,请求会被AbstractAuthenticationProcessingFilter拦截。这个过滤器从请求中提取相关的身份验证信息,比如用户名和密码,并创建一个 Authentication 对象的实例。
然后,过滤器将身份验证处理委托给配置的 AuthenticationManager

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    // 首先判断该请求是否是认证请求或者登录请求
    if (!requiresAuthentication(request, response)) { // (1)
        chain.doFilter(request, response);
        return;
    }
    try {
        Authentication authenticationResult = attemptAuthentication(request, response); // (2) 实际认证逻辑
        // 认证成功
        successfulAuthentication(request, response, chain, authenticationResult); // (3)
    }
    catch (AuthenticationException ex) {
        // 认证失败
        unsuccessfulAuthentication(request, response, ex); // (4)
    }
}

1.首先requiresAuthentication方法用于判断当前请求是否为认证请求或者登录请求,例如通常是POST /login。只有在登录认证的情况下,才需要通过这个Filter;

2.attempAuthentication方法是实际的认证逻辑,这是一个抽象方法,具体的逻辑由子类重写实现。它的规范行为是,如果认证成功,应该返回认证结果Authentication,否则以抛出异常AuthenticationException的方式表示认证失败;

3.successfulAuthentication:认证成功后,该方法会将Authentication对象放到Security Context中,这是非常关键的一步,后续需要认证结果的时候都是从Security
Context获取的,比如鉴权Filter。此外,该方法还会处理其它一些相关功能,比如RememberMe,事件发布,最后再调用AuthenticationSuccessHandler;

4.unsuccessfulAuthentication :在认证失败后,它会清空Security Context,调用RememberMe相关服务和AuthenticationFailureHandler来处理认证失败后的回调逻辑,比如跳转到错误页面。

attempAuthentication方法:
UsernamePasswordAuthenticationFilter的认证具体实现方法attempAuthentication如下:

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
        throws AuthenticationException {
    // 默认只支持POST请求
    if (this.postOnly && !request.getMethod().equals("POST")) {
        throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
    }
    // 从form表单获取用户名和密码
    String username = obtainUsername(request);
    username = (username != null) ? username.trim() : "";
    String password = obtainPassword(request);
    password = (password != null) ? password : "";
    // 构建一个用于认证的请求
    UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
            password);
    // 附加详细信息
    setDetails(request, authRequest);
    // 委托给AuthenticationManager做具体的认证
    return this.getAuthenticationManager().authenticate(authRequest);
}

attempAuthentication方法主要是从请求体总获取用户名和密码,并构建认证请求对象
,然后将剩余任务交给AuthenticationManager的authenticate()做认证

AuthenticationManager和AuthenticationProvider:
在这里插入图片描述在这里插入图片描述

AuthenticationManager接口只有一个方法,它的入参和出参都是Authentication对象。 在Spring Security中,通常会有一个默认的AuthenticationManager实现,称为ProviderManager。它实际上是一个AuthenticationProvider的集合.

AuthenticationManager会迭代遍历配置的所有AuthenticationProvider,并调用它们的authenticate()方法,直到找到一个能够成功验证用户身份的AuthenticationProvider。

AuthenticationProvider的authenticate()方法接收一个认证请求,通常是一个包含用户名和密码等认证信息的Authentication对象。该方法会进行有效性验证,并返回一个经过认证的Authentication对象,或者在认证失败时抛出相应AuthenticationException。

通过AuthenticationManager和AuthenticationProvider的配合,可以处理不同的认证逻辑,从而实现应用程序的身份验证和认证授权功能。用户可以根据自己的需求,自定义并配置不同的AuthenticationProvider,以满足特定的认证场景和安全需求。

基本执行流程图
在这里插入图片描述

1.当一个HTTP请求进来后,UsernamePasswordAuthenticationFilter会从HTTP请求体中获取用户名和密码,然后使用这些信息创建一个UsernamePasswordAuthenticationToken对象作为认证请求的参数。

2.接下来,AuthenticationManager(其实现类是ProviderManager)负责对接受到的UsernamePasswordAuthenticationToken进行认证。

3.ProviderManager会遍历配置的所有AuthenticationProvider,查找支持UsernamePasswordAuthenticationToken类型的AuthenticationProvider,然后委托其进行实际的认证工作,而在这里,匹配的就是DaoAuthenticationProvider。

4.DaoAuthenticationProvider首先调用UserDetailService获取用户信息,然后将获取到的密码(通常是编码后的密码)委托给PasswordEncoder进行验证。如果认证失败,DaoAuthenticationProvider会抛出AuthenticationException的子类表示认证失败。

5.当认证成功时,AuthenticationManager会返回一个UsernamePasswordAuthenticationToken对象作为认证结果,这个对象除了包含用户的基本信息外,最重要的是认证通过状态以及该用户拥有的权限列表,这些信息在后续的鉴权模块会用到。

6.认证结果会被放入SecurityContext,这样后续的模块(包括鉴权和用户业务模块等)如果需要这个结果(包括用户信息和权限列表),就可以通过以下方法获取:SecurityContextHolder.getContext().getAuthentication()。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值