对应版本为5.7.2,不同版本间可能有或大或小的差异,整体思想应该大同小异。
先看总结出来的下图

在前面的内容我们提到,springSecurity是通过一系列的过滤器组成的过滤器链来实现的,而认证对应的UsernamePasswordAuthenticationFilter就是springSecurity核心的一环。
下面我们再从源码一步一步看具体的实现。
在idea中双击Shift键,搜索并键入AbstractAuthenticationProcessingFilter

AbstractAuthenticationProcessingFilter类中没有Filter的入口doFilter,在父类AbstractAuthenticationProcessingFilter中。

UsernamePasswordAuthenticationFilter中重写了attemptAuthentication方法,将用户名密码封装成UsernamePasswordAuthenticationToken对象再调用ProviderManager的authenticate认证。

ProviderManager实现了AuthenticationManager接口,根据接口的描述,该接口验证会进行身份验证,返回用户身份信息以及被授予的权限。

在ProviderManager实现的authenticate中,遍历容器中的AuthenticationProvider,如果返回的result不为空则代表认证通过,再封装并返回认证信息。

通过idea的提示信息,AuthenticationProvider的实现类中无法直接找到DaoAuthenticationProvider,后者是通过继承AbstractUserDetailsAuthenticationProvider,间接实现了AuthenticationProvider接口。

我们先看下面这段AbstractUserDetailsAuthenticationProvider中实现的逻辑

先通过this.userCache.getUserFromCache(username)查询用户信息,如果查询不到,再通过retrieveUser(username, (UsernamePasswordAuthenticationToken) authentication)来match,实际debug发现是通过后者找到的,而后面这个方法是由DaoAuthenticationProvider实现的。

InMemoryUserDetailsManager的逻辑就比较简单了,实现了UserDetailsService接口,含有成员属性private final Map

最后再回顾一下文章开头贴出的调用链路图可能会更加清晰一丢丢。

整体来看可以分为三部分