在 UsernamePasswordAuthenticationFilter 源码分析 中,最后在类UsernamePasswordAuthenticationFilter
的验证方法 attemptAuthentication()
会将用户表单提交过来的用户名和密码封装成对象委托类 AuthenticationManager
的验证方法 authenticate()
进行身份验证。
那么本文主要对 AuthenticationManager
的验证方法 authenticate()
验证原理进行源码分析。
AuthenticationManager 相关类图
AuthenticationManager 验证过程涉及到的类和接口较多,先用一张类图说明各个类和接口之间的关系,如下:
-
AuthenticationManager
为认证管理接口类,其定义了认证方法authenticate()\
p
roviderManager
为认证管理类,实现了接口AuthenticationManager
,并在认证方法authenticate()
中将身份认证委托给具有认证资格的AuthenticationProvider
进行身份认证。-
AuthenticationProvider
是认证接口类,它定义了身份认证的方法 authenticate() AbstractUserDetailsAuthenticationProvider
是认证的抽象类,它实现了AuthenticationProvider
定义的认证方法authenticate();还定义了虚拟方法retrieveUser()用于查询数据库用户信息
以及additionalAuthenticationChecks()用户身份的认证(这两个方法都是抽象方法)
-
DaoAuthenticationProvider
是继承类AbstractUserDetailsAuthenticationProvider 该方法实现retrieveUser()和additionalAuthenticationChecks()两个方法
DaoAuthenticationProvider
中还具有成员变量 userDetailsService [UserDetailsService]
用作用户信息查询,以及成员变量 passwordEncoder [PasswordEncoder]
用作密码的加密及验证。
userDetailsService
是在retrieveUser方法中调用用户查询数据库用户信息,passwordEncoder
在additionalAuthenticationChecks方法中使用,用于身份的认证
流程分析
1、认证的入口为 AuthenticationManager
的 authenticate()
方法,鉴于 AuthenticationManager
是接口类,因此分析它的实现类 ProviderManager
,ProviderManager
的 authenticate()
方法代码如下:
从图中可以看出来ProviderManager 的
authenticate方法 是将认证交给AuthenticationProvider
来实现,接下来我们分析AuthenticationProvider
,由于AuthenticationProvider
是一个接口,那么我们分析实现类AbstractUserDetailsAuthenticationProvider
2、AbstractUserDetailsAuthenticationProvider
的 authenticate ()方法
retrieveUser()方法是从数据库加载用户信息,这里抽象出来这个方法,additionalAuthenticationChecks()方法密码验证,这里也是抽象出来方法,两个方法具体实现都是交给子类DaoAuthenticationProvider 来实现的,那么我们来研究一下
3、DaoAuthenticationProvider的retrieveUser方法和additionalAuthenticationChecks方法
这里是调用成员变量 userDetailsService
的方法 loadUserByUsername()
加载数据层中的用户信息
调用了成员变量 passwordEncoder
的校验方法 isPasswordValid()
对用户密码进行验证