kabal
kabal

Reputation: 2145

Adding spring-session & Redis to existing Spring Boot Spring Security configuration

Currently we have a spring-boot (1.2.1.RELEASE) application with spring-security running successfully.

We have successfully implemented concurrency control with the following configuration

@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig {

    @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
    @Configuration
    protected static class ApplicationSecurity extends WebSecurityConfigurerAdapter {

        private static final int MAX_CONCURRENT_USER_SESSIONS = 1;

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    //snipped
                    .sessionManagement()
                    .maximumSessions(MAX_CONCURRENT_USER_SESSIONS)
                    .maxSessionsPreventsLogin(true)
                    .sessionRegistry(sessionRegistry());
        }

        @Bean
        public SessionRegistry sessionRegistry() {
            SessionRegistry sessionRegistry = new SessionRegistryImpl();
            return sessionRegistry;
        }

        @Bean
        public static HttpSessionEventPublisher httpSessionEventPublisher() {
            return new HttpSessionEventPublisher();
        }
    }
}

If you try login with the same user account on 2 different sessions, the second attempt will fail, until the current user logs out, as expected and required.

This works great in a single instance environment, but we want to deploy to multiple dyno's on Herkou, and as such need to externalize the session.

spring-session + spring-boot-starter-redis seems like a great candidate for this.

From the spring-session documentation, it mentions that all we need to do is add the annotation @EnableRedisHttpSession and define a JedisConnectionFactory.

This indeed works, and adding that annotation causes the sessions to be stored in Redis, which I can see using redis-cli.

However, adding this annotation breaks the concurrency control.

With the annotation @EnableRedisHttpSession added, the SessionRegistryImpl methods are never invoked, and neither are the HttpSessionEventPublisher.sessionCreated()/sessionDestroy() methods.

This means that when the current user logs out, the other session attempting to use that username will still not be able to login, and the user that just logged out will not be able to re-login. This is because the sessions are never removed from the ???registry/repository???

Any insight into how I can have my session creation/destruction working, while using redis as the store would be greatly appreciated.

Upvotes: 2

Views: 3993

Answers (1)

Rob Winch
Rob Winch

Reputation: 21720

We do not currently have support for Spring Security's Concurrency Control and Spring Session. You can find an existing issue on GitHub.

The general idea would be to implement Spring Security's SessionRepository interface using Spring Session's SessionRepository interface.

If you would like to submit a PR it would be much appreciated!

Upvotes: 1

Related Questions