1 year ago

#359275

test-img

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

Accepted video resources