SpringScurity学习笔记

过滤器链结构

在这里插入图片描述

工作流程

1.用户登录

表单通过post请求提交,首先到达UsernamePasswordAuthenticationFilter过滤器的attemptAuthentication(HttpServletRequest request, HttpServletResponse response)方法,源码如下:

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            String username = this.obtainUsername(request);
            String password = this.obtainPassword(request);
            if (username == null) {
                username = "";
            }

            if (password == null) {
                password = "";
            }

            username = username.trim();
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
            this.setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

该方法将用户的用户名和密码封装成AuthenticationManager可以处理的Authentication对象。具体步骤如下:

  • 首先我们从构造方法中可以得知,该过滤器 只对post请求方式的"/login"接口有效;然后在该过滤器中,再利用 obtainUsernameobtainPassword 方法,提取出请求里边的用户名/密码,提取方式就是 request.getParameter.
  • 接下来会 构造一个 UsernamePasswordAuthenticationToken 对象,传入 usernamepassword。其中 username 对应了 UsernamePasswordAuthenticationToken 中的 principal 属性,而 password 则对应了它的 credentials属性。再利用 setDetails 方法details 属性赋值.
    (tips:UsernamePasswordAuthenticationToken 本身是没有 details 属性的**,**这个属性是在它的父类 AbstractAuthenticationToken 中定义的。details 是一个对象,这个对象里边存放的是 WebAuthenticationDetails 实例,该实例主要描述了 请求的 remoteAddress 以及请求的 sessionId 这两个信息。)
  • 最后一步,就是利用AuthenticationManager对象来调用 authenticate()方法去做认证校验

2.验证用户名和密码

上面说了。在最后一步会进行认证,

return this.getAuthenticationManager().authenticate(authRequest);

this.getAuthenticationManager()拿到authenticationManager代码如下:

protected AuthenticationManager getAuthenticationManager() {
        return this.authenticationManager;
    }

authenticationManager是一个接口,所以实际拿到的是它的实现类ProviderManager

public class ProviderManager implements AuthenticationManager
此处省略n行源代码

经过该类一系列骚操作(因为这一段源代码看不懂。。。),最后来到
{

算了,算了,我看不懂这个源码了,继续学习去了。。。。。

}

反正如果成功会调用其父类AbstractAuthenticationProcessingFiltersuccessfulAuthentication(...)方法,失败会调用unsuccessfulAuthentication方法,这两个方法的源码如下:

protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Authentication success. Updating SecurityContextHolder to contain: " + authResult);
        }

        SecurityContextHolder.getContext().setAuthentication(authResult);
        this.rememberMeServices.loginSuccess(request, response, authResult);
        if (this.eventPublisher != null) {
            this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
        }

        this.successHandler.onAuthenticationSuccess(request, response, authResult);
    }

    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        SecurityContextHolder.clearContext();
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Authentication request failed: " + failed.toString(), failed);
            this.logger.debug("Updated SecurityContextHolder to contain null Authentication");
            this.logger.debug("Delegating to authentication failure handler " + this.failureHandler);
        }

        this.rememberMeServices.loginFail(request, response);
        this.failureHandler.onAuthenticationFailure(request, response, failed);
    }

其实我们如果只是使用的话,仅仅需要实现userdetailservice的loaduserbyusername方法,去自定义我们的验证逻辑,然后返回一个实现了userdetail接口的对象即可,框架会自己调用。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值