`AuthenticationManager`只是一个接口,
~~~
Authentication authenticate(Authentication authentication)
throws AuthenticationException;
~~~
因此实现可以是我们选择的任何东西,但它在实践中如何工作?如果我们需要检查多个身份验证数据库或不同身份验证服务(如数据库和LDAP服务器)的组合,该怎么办?
`AuthenticationProvider`也是一个接口,和`AuthenticationManager`的功能一样,实现认证,但是多了一个方法
~~~
boolean supports(Class<?> authentication);
~~~
如果支持特定类型的authentication,则返回true,但是不代表一定能验证通过,authenticate方法仍然可以返回null.
Spring Security中的默认实现称为`ProviderManager`,它不是处理身份验证请求本身,而是委托给已配置的`AuthenticationProvider`列表,然后依次查询每个查看是否可以执行身份验证。每个提供程序将抛出异常或返回完全填充的`Authentication`对象。还记得我们的好朋友,`UserDetails`和`UserDetailsService`吗?如果没有,请回到上一章并刷新记忆。验证身份验证请求的最常用方法是加载相应的`UserDetails`并检查加载的密码与用户输入的密码。这是`DaoAuthenticationProvider`使用的方法(见下文)。加载的`UserDetails`对象 - 特别是它包含的`GrantedAuthority`(角色) - 将在构建完全填充的`Authentication`对象时使用,该对象从成功的身份验证返回并存储在`SecurityContext`中。
如果您正在使用命名空间,则会在内部创建和维护`ProviderManager`的实例,并使用身份验证命名空间提供程序元素向其添加提供程序(请参阅命名空间章节)。在这种情况下,您不应在应用程序上下文中声明`ProviderManager `bean。但是,如果您没有使用命名空间,那么您将声明它如下:
~~~
<bean id="authenticationManager"
class="org.springframework.security.authentication.ProviderManager">
<constructor-arg>
<list>
<ref local="daoAuthenticationProvider"/>
<ref local="anonymousAuthenticationProvider"/>
<ref local="ldapAuthenticationProvider"/>
</list>
</constructor-arg>
</bean>
~~~
在上面的例子中,我们有三个提供者。它们按所示顺序(使用`List`暗示)进行尝试,每个提供程序都可以尝试进行身份验证,或者通过简单地返回`null`来跳过身份验证。如果所有实现都返回null,则`ProviderManager`将抛出`ProviderNotFoundException`。如果您有兴趣了解有关链接提供程序的更多信息,请参阅`ProviderManager` Javadoc。
诸如Web表单登录处理过滤器之类的身份验证机制将引用`ProviderManager`,并将其调用以处理其身份验证请求。您需要的提供程序有时可以与身份验证机制互换,而在其他时候,它们将依赖于特定的身份验证机制。例如,`DaoAuthenticationProvider`和`LdapAuthenticationProvider`与提交简单用户名/密码身份验证请求的任何机制兼容,因此可以使用基于表单的登录或HTTP基本身份验证。另一方面,某些身份验证机制会创建一个身份验证请求对象,该对象只能由单一类型的`AuthenticationProvider`进行解释。一个例子是JA-SIG CAS,它使用服务票据的概念,因此只能由`CasAuthenticationProvider`进行身份验证。您不必过于担心这一点,因为如果您忘记注册合适的提供程序,那么在尝试进行身份验证时,您只会收到`ProviderNotFoundException`。
- 架构
- 9.技术概述
- 9.1 运行环境
- 9.2 核心组件
- 9.2.1 SecurityContextHolder, SecurityContext and Authentication Objects
- 9.2.2 The UserDetailsService
- 9.2.3 GrantedAuthority
- 9.2.4 总结
- 9.3 验证
- 9.3.1 在Spring Security中验证是什么
- 9.3.2 直接设置SecurityContextHolder内容
- 9.4 web应用中的验证
- 9.4.1 ExceptionTranslationFilter
- 9.4.2 AuthenticationEntryPoint
- 9.4.3 验证机制
- 9.4.4 在请求之间存储SecurityContext
- 9.5 Spring Security中的访问控制(授权)
- 9.5.1 Security and AOP Advice
- 9.5.2 Secure Objects and the AbstractSecurityInterceptor
- 什么是配置属性
- RunAsManager
- AfterInvocationManager
- 扩展安全对象模型
- 9.6 本地化
- 10 核心服务
- 10.1 The AuthenticationManager, ProviderManager and AuthenticationProvider
- 10.1.1 成功验证时擦除凭据
- 10.1.2 DaoAuthenticationProvider
- 10.2 UserDetailsService实现
- 10.2.1 In-Memory Authentication
- 10.2.2 JdbcDaoImpl
- Authority Groups
- 10.3 Password Encoding
- 10.3.1 密码发展史
- 10.3.2 DelegatingPasswordEncoder
- 密码存储格式
- 密码编码
- 密码比对
- 入门体验
- 排除故障
- 10.3.3 BCryptPasswordEncoder
- 10.3.4 Pbkdf2PasswordEncoder
- 10.3.5 SCryptPasswordEncoder
- 10.3.6 其他PasswordEncoders
- 10.4 Jackson的支持
- 11 测试方法安全
- 12 集成spring mvc测试
- 13 webflux支持
- 14 安全过滤器链
- 14.1 DelegatingFilterProxy
- 14.2 FilterChainProxy
- 14.2.1 绕过过滤链
- 14.3 过滤器顺序
- 14.4 匹配请求和http防火墙
- 14.5 与其他基于过滤器的框架一起使用
- 14.6 Advanced Namespace Configuration
- 15. 核心的安全过滤器
- 15.1 FilterSecurityInterceptor
- 15.2 ExceptionTranslationFilter
- 15.3 SecurityContextPersistenceFilter
- 15.4 UsernamePasswordAuthenticationFilter