I am working on Spring Security Java-based configuration.
I have created my own MyAuthenticationProvider
which I want to register in the ProviderManager
(single instance of AuthenticationManager
).
I have found that ProviderManager
has a list of providers to which I can register my single
MyAuthenticationProvider
.
Here is the part of my Configuration:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(MyAuthenticationProvider);
}
}
I found out that AuthenticationManagerBuilder
has parentAuthenticationManager
, defaultUserDetailsService
and many other fields.
My questions are:
- Where is this
@Autowired
annotation adding AuthenticationManagerBuilder
auth from?
Is the AuthenticationManagerBuilder
already created in the application context?
- What would be the default state of
AuthenticationManagerBuilder
which is being injected? By default state I mean will there be some parentAuthenticationManager
, authenticationProvider
s already registered in the AuthenticationManagerBuilder
?
- If I am adding
auth.authenticationProvider(MyAuthenticationProvider)
, does this mean that I am adding one more provider in the AuthenticationManagerBuilder
?
What does this mean? Taken from Spring Documentation
The name of the configureGlobal method is not important. However, it
is important to only configure AuthenticationManagerBuilder in a class
annotated with either @EnableWebSecurity, @EnableWebMvcSecurity,
@EnableGlobalMethodSecurity, or @EnableGlobalAuthentication. Doing
otherwise has unpredictable results.
Answer for 1:
@EnableWebSecurity
is meta-annotated with @EnableGlobalAuthentication
...
@EnableGlobalAuthentication
@Configuration
public @interface EnableWebSecurity {
...
and @EnableGlobalAuthentication
imports AuthenticationConfiguration
:
...
@Import(AuthenticationConfiguration.class)
@Configuration
public @interface EnableGlobalAuthentication {
}
In AuthenticationConfiguration
, you'll see that an AuthenticationManagerBuilder
bean is declared:
...
@Bean
public AuthenticationManagerBuilder authenticationManagerBuilder(
ObjectPostProcessor<Object> objectPostProcessor, ApplicationContext context) {
...
}
When you @Autowire
an AuthenticationManagerBuilder
, this is the one that you will get. You have several methods at your disposal to easily configure in-memory, jdbc, ldap,... authentication.
Answer for 2:
Background:
The Spring Security Java config goes through several stages to seamlessly incorporate your configurations with the ApplicationContext
.One place where this comes together is in the getHttp()
method in WebSecurityConfigurerAdapter
.
For example, this is an excerpt:
AuthenticationManager authenticationManager = authenticationManager();
authenticationBuilder.parentAuthenticationManager(authenticationManager);
To give you an idea of how "not-straightforward" the sequence of configuration is, the authenticationManager variable above will be either:
- The authentication manager you added by overriding
configure(AuthenticationManagerBuilder auth)
- OR: The authentication manager you added in the method that
@Autowired
the AuthenticationManagerBuilder
bean from AuthenticationConfiguration
- OR: an AuthenticationManager bean found in the context
By default state I mean will there be some [...] authenticationProviders already registered in the AuthenticationManagerBuilder
If you look at AuthenticationConfiguration
, you'll see that by default, the InitializeUserDetailsBeanManagerConfigurer
is applied to the AuthenticationManagerBuilder
bean. As long as it finds a UserDetailsService
bean in the context and no other provider has been added, it will add a DaoAuthenticationProvider
. This is why in the Spring Security reference, only providing a @Bean UserDetailsService
bean is sufficient.
But once you add an authentication provider as you did, the "default" provider is not registered.
Answer for 3:
Yes. The code of AuthenticationManagerBuilder adds your provider:
public AuthenticationManagerBuilder authenticationProvider(AuthenticationProvider authenticationProvider) {
this.authenticationProviders.add(authenticationProvider);
return this;
}
Answer for 4 is simple:
It means that, once you have one of that annotations, you can name your method as you wish:
@Configuration
@EnableWebSecurity //or @EnableWebMvcSecurity or @EnableGlobalMethodSecurity....
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void myCoolMethodName(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(MyAuthenticationProvider);
}
}
"Doing otherwise has unpredictable results"
If you keep the name but not the annotations, it may not work.