When we use a custom filter we need to inject a bean of AuthenticationManager.
As far as I remember If we use the default filter then spring automatically provides Authentication Manager. This lets 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 crate and inject a bean of AuthenticationManager to the filter.
Can you please explain what's wrong with my assumption? Why do we need to crate a bean while it is already present?
Thanks in advance.
CodePudding user response:
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);