Spring Boot 2.1.5.RELEASE Spring Security 版本:5.1.5-RELEASE Spring Security 官方文档
ProviderManager 是 AuthenticationManager 最常见的实现。
ProviderManager 持有了 AuthenticationProvider 列表。每个 AuthenticationProvider 都能够判定当前 authentication(身份认证)是成功 或者失败,或者当前 AuthenticationProvider 无法判定,需要交由下游的 AuthenticationProvider 进行判定。如果没有一个 AuthenticationProvider 能够进行 authentication(身份认证),本次 authentication(身份认证)判定为失败 ProviderNotFoundException ,该异常是特殊的 AuthenticationException ,表示当前 ProviderManager 配置配置支持授权类型的 AuthenticationProvider 。
ProviderManager 处理流程逻辑图:

实际上,每个 AuthenticationProvider 知道如何执行完成特殊类型的 authentication(身份认证)。
如:有的 AuthenticationProvider 支持 username/password 认证,有的 AuthenticationProvider 支持 SAML 断言认证。AuthenticationManager 持有多个 AuthenticationProvider ,每个 AuthenticationProvider 支持特殊类型的 authentication(身份认证), AuthenticationProvider 集合支持多种身份类型身份认证。
ProviderManager 允许配置父级的 AuthenticationManager ,该配置是可选配置,当 ProviderManager 持有 AuthenticationProvider 无法进行身份认证时,会父级 AuthenticationManager 处理。父级 AuthenticationManager 可以是其任何实现,不过最常见的实现是 ProviderManager 。
相关逻辑图如下:
实际上,多个 ProviderManager 示例可以共享同一个父级 AuthenticationManager 。这是一个比较常见的情况,在存在多个 SecurityFilterChain 示例且具有某些共同身份认证的长中,补哦过在不同的 ProviderManager 实例中会有不同的身份认证机制。

默认情况下,ProviderManager将尝试从成功的身份验证请求返回的身份验证对象中清除任何敏感的凭据信息。这可以防止诸如密码之类的信息在HttpSession中被保留的时间超过必要的时间。
在使用用户对象的缓存(例如,在无状态应用程序中提高性能)时,这可能会导致问题。如果身份验证包含对缓存中的对象(例如UserDetails实例)的引用,并且删除了它的凭据,那么将不再可能根据缓存的值进行身份验证。如果您正在使用缓存,则需要考虑到这一点。一个明显的解决方案是首先复制对象,要么在缓存实现中,要么在创建返回的身份验证对象的AuthenticationProvider中。或者,您可以禁用ProviderManager上的eraseCredentialsAfterAuthentication属性。有关更多信息,请参阅Javadoc。
