在Spring Security Config
中,AuthenticationManagerBuilder
是一个SecurityBuilder
,其目的是根据所设置的属性构建一个AuthenticationManager
(实现类使用ProviderManager
)。
AuthenticationManagerBuilder
典型的用法是 :
AuthenticationManager
(可选,缺省值无):#parentAuthenticationManager()
;#authenticationEventPublisher()
;false
,可选):#eraseCredentials()
;SecurityConfigurer
(可以应用多个,也可以一个都不应用)
#jdbcAuthentication()
,对应JdbcUserDetailsManagerConfigurer
#inMemoryAuthentication()
, 对应InMemoryUserDetailsManagerConfigurer
#ldapAuthentication()
, 对应LdapAuthenticationProviderConfigurer
这里每个
SecurityConfigurer
都用于生成一个AuthenticationProvider
并添加到所配置的目标AuthenticationManagerBuilder
上
UserDetailsService
(也可以不提供)
其实是将一个
UserDetailsService
包装成了一个SecurityConfigurer DaoAuthenticationConfigurer
然后应用到目标AuthenticationManagerBuilder
上,最终也是生成一个AuthenticationProvider
并添加到所配置的目标AuthenticationManagerBuilder
上
AuthenticationProvider
(也可以不提供)
注意:以上2,3,4 步骤中提供
AuthenticationProvider
必须设置至少一个或者双亲AuthenticationManager
必须要设置;
#build
方法构建目标AuthenticationManager
供使用方式用源代码版本 : Spring Security Config 5.1.4.RELEASE
package org.springframework.security.config.annotation.authentication.builders;
// 省略 imports
/**
* SecurityBuilder used to create an AuthenticationManager. Allows for
* easily building in memory authentication, LDAP authentication, JDBC based
* authentication, adding UserDetailsService, and adding
* AuthenticationProvider's.
*
* @author Rob Winch
* @since 3.2
*/
public class AuthenticationManagerBuilder
extends
AbstractConfiguredSecurityBuilder<AuthenticationManager, AuthenticationManagerBuilder>
implements ProviderManagerBuilder<AuthenticationManagerBuilder> {
private final Log logger = LogFactory.getLog(getClass());
private AuthenticationManager parentAuthenticationManager;
private List<AuthenticationProvider> authenticationProviders = new ArrayList<>();
private UserDetailsService defaultUserDetailsService;
private Boolean eraseCredentials;
private AuthenticationEventPublisher eventPublisher;
/**
* Creates a new instance
* @param objectPostProcessor the ObjectPostProcessor instance to use.
*/
public AuthenticationManagerBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
super(objectPostProcessor, true);
}
/**
* Allows providing a parent AuthenticationManager that will be tried if this
* AuthenticationManager was unable to attempt to authenticate the provided
* Authentication.
*
* @param authenticationManager the AuthenticationManager that should be used
* if the current AuthenticationManager was unable to attempt to authenticate
* the provided Authentication.
* @return the AuthenticationManagerBuilder for further adding types of
* authentication
*/
public AuthenticationManagerBuilder parentAuthenticationManager(
AuthenticationManager authenticationManager) {
if (authenticationManager instanceof ProviderManager) {
eraseCredentials(((ProviderManager) authenticationManager)
.isEraseCredentialsAfterAuthentication());
}
this.parentAuthenticationManager = authenticationManager;
return this;
}
/**
* Sets the AuthenticationEventPublisher
*
* @param eventPublisher the AuthenticationEventPublisher to use
* @return the AuthenticationManagerBuilder for further customizations
*/
public AuthenticationManagerBuilder authenticationEventPublisher(
AuthenticationEventPublisher eventPublisher) {
Assert.notNull(eventPublisher, "AuthenticationEventPublisher cannot be null");
this.eventPublisher = eventPublisher;
return this;
}
/**
*
*
* @param eraseCredentials true if AuthenticationManager should clear the
* credentials from the Authentication object after authenticating
* @return the AuthenticationManagerBuilder for further customizations
*/
public AuthenticationManagerBuilder eraseCredentials(boolean eraseCredentials) {
this.eraseCredentials = eraseCredentials;
return this;
}
/**
* Add in memory authentication to the AuthenticationManagerBuilder and return
* a InMemoryUserDetailsManagerConfigurer to allow customization of the in
* memory authentication.
*
*
* This method also ensure that a UserDetailsService is available for the
* #getDefaultUserDetailsService() method. Note that additional
* UserDetailsService's may override this UserDetailsService as the
* default.
*
*
* @return a InMemoryUserDetailsManagerConfigurer to allow customization of
* the in memory authentication
* @throws Exception if an error occurs when adding the in memory authentication
*/
public InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> inMemoryAuthentication()
throws Exception {
return apply(new InMemoryUserDetailsManagerConfigurer<>());
}
/**
* Add JDBC authentication to the AuthenticationManagerBuilder and return a
* JdbcUserDetailsManagerConfigurer to allow customization of the JDBC
* authentication.
*
*
* When using with a persistent data store, it is best to add users external of
* configuration using something like Flyway or Liquibase to create the schema and adding
* users to ensure these steps are only done once and that the optimal SQL is used.
*
*
*
* This method also ensure that a UserDetailsService is available for the
* #getDefaultUserDetailsService() method. Note that additional
* UserDetailsService's may override this UserDetailsService as the
* default. See the User Schema section of the reference for the default schema.
*
*
* @return a JdbcUserDetailsManagerConfigurer to allow customization of the
* JDBC authentication
* @throws Exception if an error occurs when adding the JDBC authentication
*/
public JdbcUserDetailsManagerConfigurer<AuthenticationManagerBuilder> jdbcAuthentication()
throws Exception {
return apply(new JdbcUserDetailsManagerConfigurer<>());
}
/**
* Add authentication based upon the custom UserDetailsService that is passed
* in. It then returns a DaoAuthenticationConfigurer to allow customization of
* the authentication.
*
*
* This method also ensure that the UserDetailsService is available for the
* #getDefaultUserDetailsService() method. Note that additional
* UserDetailsService's may override this UserDetailsService as the
* default.
*
*
* @return a DaoAuthenticationConfigurer to allow customization of the DAO
* authentication
* @throws Exception if an error occurs when adding the UserDetailsService
* based authentication
*/
public <T extends UserDetailsService> DaoAuthenticationConfigurer<AuthenticationManagerBuilder, T>
userDetailsService(T userDetailsService) throws Exception {
this.defaultUserDetailsService = userDetailsService;
return apply(new DaoAuthenticationConfigurer<>(
userDetailsService));
}
/**
* Add LDAP authentication to the AuthenticationManagerBuilder and return a
* LdapAuthenticationProviderConfigurer to allow customization of the LDAP
* authentication.
*
*
* This method does NOT ensure that a UserDetailsService is available
* for the #getDefaultUserDetailsService() method.
*
* @return a LdapAuthenticationProviderConfigurer to allow customization of
* the LDAP authentication
* @throws Exception if an error occurs when adding the LDAP authentication
*/
public LdapAuthenticationProviderConfigurer<AuthenticationManagerBuilder> ldapAuthentication()
throws Exception {
return apply(new LdapAuthenticationProviderConfigurer<>());
}
/**
* Add authentication based upon the custom AuthenticationProvider that is
* passed in. Since the AuthenticationProvider implementation is unknown, all
* customizations must be done externally and the AuthenticationManagerBuilder
* is returned immediately.
*
*
* This method does NOT ensure that the UserDetailsService is available
* for the #getDefaultUserDetailsService() method.
*
* Note that an Exception might be thrown if an error occurs when adding the AuthenticationProvider.
*
* @return a AuthenticationManagerBuilder to allow further authentication to
* be provided to the AuthenticationManagerBuilder
*/
public AuthenticationManagerBuilder authenticationProvider(
AuthenticationProvider authenticationProvider) {
this.authenticationProviders.add(authenticationProvider);
return this;
}
@Override
protected ProviderManager performBuild() throws Exception {
if (!isConfigured()) {
logger.debug("No authenticationProviders and no parentAuthenticationManager defined. Returning null.");
return null;
}
ProviderManager providerManager = new ProviderManager(authenticationProviders,
parentAuthenticationManager);
if (eraseCredentials != null) {
providerManager.setEraseCredentialsAfterAuthentication(eraseCredentials);
}
if (eventPublisher != null) {
providerManager.setAuthenticationEventPublisher(eventPublisher);
}
providerManager = postProcess(providerManager);
return providerManager;
}
/**
* Determines if the AuthenticationManagerBuilder is configured to build a non
* null AuthenticationManager. This means that either a non-null parent is
* specified or at least one AuthenticationProvider has been specified.
*
*
* When using SecurityConfigurer instances, the
* AuthenticationManagerBuilder will not be configured until the
* SecurityConfigurer#configure(SecurityBuilder) methods. This means a
* SecurityConfigurer that is last could check this method and provide a
* default configuration in the SecurityConfigurer#configure(SecurityBuilder)
* method.
*
* @return true, if AuthenticationManagerBuilder is configured, otherwise false
*/
public boolean isConfigured() {
return !authenticationProviders.isEmpty() || parentAuthenticationManager != null;
}
/**
* Gets the default UserDetailsService for the
* AuthenticationManagerBuilder. The result may be null in some circumstances.
*
* @return the default UserDetailsService for the
* AuthenticationManagerBuilder
*/
public UserDetailsService getDefaultUserDetailsService() {
return this.defaultUserDetailsService;
}
/**
* Captures the UserDetailsService from any UserDetailsAwareConfigurer
* .
*
* @param configurer the UserDetailsAwareConfigurer to capture the
* UserDetailsService from.
* @return the UserDetailsAwareConfigurer for further customizations
* @throws Exception if an error occurs
*/
private <C extends UserDetailsAwareConfigurer<AuthenticationManagerBuilder, ? extends UserDetailsService>>
C apply(C configurer) throws Exception {
this.defaultUserDetailsService = configurer.getUserDetailsService();
return (C) super.apply(configurer);
}
}
*Spring Security : 概念模型 AuthenticationManager 认证管理器