💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
`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`。