Issue
When we use a custom filter we need to inject a bean of type AuthenticationManager
.
As far as I remember, if we use the default filter then Spring automatically provides Authentication Manager. This leads me to the conclusion that there is already an AuthenticationManager
bean in the Spring context (from my understanding).
But the problem is that my assumption is not true. I have to create and inject a bean of AuthenticationManager
to the filter.
What is wrong with my assumption? Why do we need to crate a bean while it is already present?
Solution
Spring uses AuthenticationManager
to find appropriate authentication provider but didn't register AuthenticationManager
as a bean by default. see the source code of HttpSecurityConfiguration
class.
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
WebSecurityConfigurerAdapter.LazyPasswordEncoder passwordEncoder = new WebSecurityConfigurerAdapter.LazyPasswordEncoder(
this.context);
AuthenticationManagerBuilder authenticationBuilder = new WebSecurityConfigurerAdapter.DefaultPasswordEncoderAuthenticationManagerBuilder(
this.objectPostProcessor, passwordEncoder);
authenticationBuilder.parentAuthenticationManager(authenticationManager());
HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
// @formatter:off
http
.csrf(withDefaults())
.addFilter(new WebAsyncManagerIntegrationFilter())
.exceptionHandling(withDefaults())
.headers(withDefaults())
.sessionManagement(withDefaults())
.securityContext(withDefaults())
.requestCache(withDefaults())
.anonymous(withDefaults())
.servletApi(withDefaults())
.apply(new DefaultLoginPageConfigurer<>());
http.logout(withDefaults());
// @formatter:on
return http;
}
private AuthenticationManager authenticationManager() throws Exception {
return (this.authenticationManager != null) ? this.authenticationManager
: this.authenticationConfiguration.getAuthenticationManager();
}
as you can see it register an authentication manager builder in HttpSecurity
. later in HttpSecurity
class it will use this builder to build an authentication manager and register it in shared objects [see method beforeConfigure()
in HttpSecurity
].
@Override
protected void beforeConfigure() throws Exception {
setSharedObject(AuthenticationManager.class, getAuthenticationRegistry().build());
}
and whenever it needs authentication manager uses HttpSecurity
to get that, like the following:
AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
Answered By - h a
Answer Checked By - Cary Denson (JavaFixing Admin)