SpringSecurity RememberMeServices not injected via annotations
I am trying to configure SpringSecurity to work with Remember Me authentication.
Here is my Java config:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Autowired
DatabasePersistentTokeRepositoryImpl databasePersistentTokeRepositoryImpl;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authenticationProvider(rememberMeAuthenticationProvider())
.rememberMe().tokenRepository(databasePersistentTokeRepositoryImpl).tokenValiditySeconds((int) TimeUnit.SECONDS.convert(7, TimeUnit.DAYS))
.and()
.csrf().disable();
}
@Bean()
public AuthenticationProvider rememberMeAuthenticationProvider() {
return new RememberMeAuthenticationProvider("KEY");
}
@Bean()
public TokenBasedRememberMeServices rememberMeServices() {
TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("KEY", userDetailsService);
rememberMeServices.setAlwaysRemember(true);
return rememberMeServices;
}
}
I can see that memMeServices is not being entered in RememberMeConfigurer. And this leads to the creation of RememberMeAuthenticationFilter that references the wrong memMeServices.
The Spring Security documentation contains a section describing this process using XML. http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#session-mgmt
What's wrong with my injection and is it possible to do it without XML?
source to share
You don't enter it. For RememberMeConfigurer
there is no auto installation. Also why are you configuring so many beans?
RememberMeAuthenticationProvider
already created for you, if you want to use a different key, specify it with key("KEY")
. This, in turn, will be used to create RememberMeServices
.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService userDetailsService;
@Autowired
DatabasePersistentTokeRepositoryImpl databasePersistentTokeRepositoryImpl;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.key("KEY")
.tokenRepository(databasePersistentTokeRepositoryImpl)
.tokenValiditySeconds((int) TimeUnit.SECONDS.convert(7, TimeUnit.DAYS))
.and()
.csrf().disable();
}
}
If you really need to set the property alwaysRemember
to true, you can use ObjectPostProcessor
to publish the filtering process and configure RememberMeServices
from there.
You would also enter the wrong type RememberMeServices
, as the one configured does not use PersistentTokeRepository
.
source to share
Just to provide some example code that @ m-deinum would suggest for ObjectPostProcessor
that sets alwaysRemember to true, it would look like this:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.rememberMe()
.key("KEY")
.tokenRepository(databasePersistentTokeRepositoryImpl)
.tokenValiditySeconds((int) TimeUnit.SECONDS.convert(7, TimeUnit.DAYS))
.withObjectPostProcessor( new ObjectPostProcessor<RememberMeAuthenticationFilter>() {
@Override
public <O extends RememberMeAuthenticationFilter> O postProcess( O object) {
RememberMeAuthenticationFilter rmaf = (RememberMeAuthenticationFilter)
PersistentTokenBasedRememberMeServices rms = (PersistentTokenBasedRememberMeServices)rmaf.getRememberMeServices();
rms.setAlwaysRemember( true );
return object;
}
})
.and()
.csrf().disable();
}
source to share