一、认证流程图
假设系统当前没有任何用户登录且没有任何的用户缓存。认证流程如下图所示:

二、过程详解
1) 用户发起表单验证后,首先会被UsernamePasswordAuthenticationFilter捕获。

UsernamePasswordAuthenticationFilter中根据用户表单信息中的用户名和密码构建UsernamePasswordAuthenticationToken,并将其交给AuthenticationManager实现认证过程。
但在大部分情况下,我们会在自定义的表单处理接口中构建UsernamePasswordAuthenticationToken,然后通过authenticationManagerBuilder.getObject()获得AuthenticationManager,进而实现认证流程。
UsernamePasswordAuthenticationToken及其类图继承关系如下所示:


此外,AuthenticationManager本身不包含任何的认证逻辑,其核心是管理所有的AuthenticationProvider,本质上是由AuthenticationProvider来实现认证。
2) 然后到ProviderManager,该类是AuthenticationManager的实现类,负责管理AuthenticationProvider,每一种AuthenticationProvider表示一种认证逻辑(Spring Security 支持多种认证逻辑)。

通过ProviderManager的authenticate()方法进一步实现认证过程,如下图所示:

通过getProviders().iterator()得到含AuthenticationProvider的迭代器,并通过provider.supports()方法判断当前的AuthenticationProvider是否支持当前的认证逻辑。若支持,接下来交由AbstractUserDetailsAuthenticationProvider的authenticate()实现进一步的认证。
3) 接下来的信息认证是交给AuthenticationProvider的抽象类AbstractUserDetailsAuthenticationProvider来实现,实现方法主要是authenticate()。

由 DaoAuthenticationProvider实现retrieveUser()方法,如下所示:

4) 成功获得UserDetails后,开始进行一系列的认证:

用户身份信息的认证校验会经过前置校验、额外校验和后置校验。若所有的认证校验均通过会调用createSuccessAuthentication()方法并返回认证信息,否则会抛出响应的异常来说明认证不通过。
createSuccessAuthentication()方法的调用过程如下所示:

在该方法中重新创建了UsernamePasswordAuthenticationToken,且此时用户身份已认证通过,所以将authorities注入,并设置authenticated为true,即已认证。
5) 最后认证信息会传回UsernamePasswordAuthenticationFilter,并在其父类AbstractAuthenticationProcessingFilter的doFilter()中,根据认证的成功或失败调用相应的handler。
