1 year ago
#359275
Umang Desai
Cannot prevent Multiple sessions for same user in spring security + redis
I am using spring security 5.6.0 with spring session data redis 2.6.0, spring boot 2.6.1.
I am trying to prevent concurrent logins for the same user. But it does not logs out the previous login instance. Basically I can have two sessions in two different browsers for the same user. Also I want to have FIFO behaviour for login sessions.
I tried adding following still it allows multiple concurrent user logins.httpSecurity.sessionManagement().maximumSessions(1);
In database I have max_concurrent_sessions with value 1 for all users. I even tried overriding Hashcode and equals method as suggestted in similar questions.
I have following configurations for spring security
httpSecurity.httpBasic().disable()
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers(configurationService.getWebSecurityProperties().getAllowedUrls()).permitAll()
.anyRequest().authenticated()
.and().sessionManagement().sessionAuthenticationStrategy(sessionAuthenticationStrategy)
.and()
.formLogin()
.successHandler(customLoginSuccessHandler) //customLoginSuccessHandler implements AuthenticationSuccessHandler
.failureHandler(authenticationFailureHandler) //CustomLoginFailureHandler extends SimpleUrlAuthenticationFailureHandler
.and()
.logout().logoutSuccessHandler(logoutSuccessHandler)
.and()
.addFilterBefore(corsFilter, WebAsyncManagerIntegrationFilter.class)
.addFilterBefore(metadataGeneratorFilter, ChannelProcessingFilter.class)
.csrf().disable();
I have CompositeSessionAuthenticationStrategy configuration with following configs
@Bean
SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new CompositeSessionAuthenticationStrategy(Arrays.asList(
sessionFixationProtectionStrategy(),
customConcurrentSessionControlAuthenticationStrategy,
registerSessionAuthenticationStrategy()
));
}
@Bean
SessionFixationProtectionStrategy sessionFixationProtectionStrategy() {
SessionFixationProtectionStrategy ret = new SessionFixationProtectionStrategy();
ret.setMigrateSessionAttributes(false);
return ret;
}
@Bean
RegisterSessionAuthenticationStrategy registerSessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(sessionRegistory);
}
customConcurrentSessionControlAuthenticationStrategy implementation is as follows
@Override
protected int getMaximumSessionsForThisUser(Authentication authentication) {
LOGGER.debug("Custom Concurrent Control Bean called.");
if (authentication != null) {
User user = (User) authentication.getPrincipal();
if (user != null) {
UserLoginBean userLogin = userManagementService.findUserByUsername(user.getUsername());
if (userLogin != null) {
return userLogin.getMaxConcurrentSessions();
}
}
}
return 1;
}
@Override
protected void allowableSessionsExceeded(List<SessionInformation> sessions, int allowableSessions,
SessionRegistry registry) throws SessionAuthenticationException {
super.allowableSessionsExceeded(sessions, allowableSessions, registry);
List<SessionInformation> expiredSessions = extractExpiredSessionInformation(sessions);
if (expiredSessions == null || expiredSessions.isEmpty()) {
return;
}
for (SessionInformation each : expiredSessions) {
registry.removeSessionInformation(each.getSessionId());
}
}
private List<SessionInformation> extractExpiredSessionInformation(List<SessionInformation> sessions) {
if (sessions == null || sessions.isEmpty()) {
return new ArrayList<>();
}
List<SessionInformation> ret = new ArrayList<>();
for (SessionInformation each : sessions) {
if (each.isExpired()) {
ret.add(each);
}
}
return ret;
}
java
spring-boot
spring-security
spring-session
spring-oauth2
0 Answers
Your Answer