SpringSecurity框架分析和UsernamePasswordAuthencationFilte表单认证过滤器的源码分析

进行debug断点

  • 首先是在UserDetailsService的实现类中的sql语句进行断点,项目中的首先的过滤器是applicationFilterChain 这个过滤器是tomcat容器来管理过滤器链,且作用是将项目中分散的过滤器组织起来,也就是职责链模式,简单来说因为执行的过程是一个入栈的过程,所以这个过滤器是整个指责链的头且还负责收尾;
    SpringSecurity框架分析和UsernamePasswordAuthencationFilte表单认证过滤器的源码分析_第1张图片

  • 因为我们要看的是SpringSecurity中的过滤器所以我们继续往下F6
    接下来有两个过滤器的代理对象,第一个因为与想看的无关所以就跳过,现在到了FilterchainProxy 这个过滤器就是SpringSecuruty中过滤器的代理对象,从这里我们就可以开始了

  • 进入代理对象的doFilterInternal方法中我们可以看到首先Request和Response都被上了防火墙,接下来就是的到来自Spring框架中的13个认证过滤器;如图

  • 接下来我们进入vfc.dofilter方法中看他是如何执行;如下图;可以看里面是一个对这13个认证过滤器的迭代,其中currentPosition是索引,现在是要开始弄进入第二个,为了更方便,所以我过了迭代了一次,且在dofilter中也打断点,可以看到右边第一个箭头处,这是我们的另外一个线程,可以看到关于Header的认证方式的过滤器已经执行;现在开始迭代的是第二个过滤器;
    -因为我要看的是表单认证UsernamePasswordAuthencationFilte所以还得继续往下迭代;当currentPosition为5的时候我们进入dofilter就是进入这个过滤器
    -现在进入了UsernamePasswordAuthencationFilte过滤器;如下图;在相关方法中,我们大体可以看出:首先我们是有一个临时认证对象Authentication,这个应该就是要进行认证的对象,且如果这个对象成功了不为null的话就会存入session中,其次失败了也会有unsuccessfulAuthentication(request, response, failed) 方法;成功了会有successfulAuthentication(request, response, chain, authResult);

  • 进入attemptAuthentication,也就是临时对象,同时这个方法里面也是对表单的认证的入口方法SpringSecurity框架分析和UsernamePasswordAuthencationFilte表单认证过滤器的源码分析_第2张图片

  • 进入如下图;可以看到这个方式是对传过来的表单账号密码进行了一个封装和格式化;最后分装成了一个UsernamePasswordAuthenticationToken;在图中可以看到这个token对象的相关属性,账号密码和属性等等;而这个方法return回去的递归调用就是对这个账号密码的认证;可以看到,首先this.getAuthenticationManager() 这个方法先获得系统的认证管理器,来调用authenticate 来完成认证;接下来的话我们就可以进入其中一探究竟
    -进入认证方法authenticate中如下图;且关键方法我已经标记;

  • 首先框架是先获取了认证对象的字节码对象,可以看到这个对象在整个方法中只在我标记的第四个位子被调用,且是用来做对比;如下图中所示,迭代了当前提供者能否支持的认证方式,如果支持则会进入provider所提供的认证方法;正如图所示当前的认证方式是DaoAuthenticationProvider 与我们所采用的一致,所以我们可以进入方法中查看

  • 进入认证方法;如下图所示;首先是账号进行排空,然后看缓存中是否有这个对象,由于本次是没有的所以UserDtails对象是空的null,所以到了第二个箭头;进入==retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication);==方法中

  • 进入方法中;如下图:主要的一步loadedUser = this.getUserDetailsService().loadUserByUsername(username);
    (调用我们自己的UserDetailsService来去数据库查用户,按照用户名查出来的用户的详细信息)封装成UserDetails
    我们进入其中

  • 进入里面就可以发现这个是我们自己写的一个通过DAO查询的UserDetailsService 的实现类:

  • 由于查询成功;我们的UserDetails loadedUser 是有值的,且同时我们可以看这个类的属性值 如下图;可以知道我们还可以==设置密码有效期,账户激活…==等等功能呢

  • 接下来就是将这个查询出来的loadedUser对象返回出去;如图;所以现在的user是有值的了

  • 接下来就得往下走;如图标示:在认证方法之前会有preAuthenticationChecks.check(user);;之后会有postAuthenticationChecks.check(user);(后置认证,检查密码是否过期);而additionalAuthenticationChecks 就是对账号密码的认证

  • 接下来我们进去preAuthenticationChecks.check(user); 去看看吧;如图;就是对user对象上那些属性的检测,,没有则抛出异常;

  • 在进入additionalAuthenticationChecks方法中 如图;可以知道比较的是刚刚查出来的UserDtails对象和框架临时的之前的token对象之间的比较,主要的比较我标出,同时可以看到默认的加密是采用的是BCrypt的加密,也就是MD5+随机数

  • 然后就是postAuthenticationChecks.check(user);(后置认证,检查密码是否过期) 如图

  • 就下来就是比较重要的一个方法createSuccessAuthentication:可以看到框架 将认证成功信息重新封装成UsernamePasswordAuthenticationToken
    3.3)3.2又返回了一个新的UsernamePasswordAuthenticationToken,然后擦掉密码
    如图:

  • 接下来就是将这个user存入缓存中;如图:SpringSecurity框架分析和UsernamePasswordAuthencationFilte表单认证过滤器的源码分析_第3张图片

  • 最终这个认证方法就结束啦!跳出返回到了系统认证管理器类中:同时可以看到result这个实体的属性:authenticated变为true代表被认证成功

  • 最后通知所以过滤器filter认证成功 如图

-接下来的就是回栈了 就不继续了

如果有过程中有啥问题,希望大家指出,共勉哈哈;惨痛经验断点的标记宁可多标,可以把自己认为有意义的标上

如果觉得文章拖拉 自己还总结了一份思维图以便记忆

你可能感兴趣的:(java,Spring,SpringSecurity)