現在、spring-security が正常に実行されている spring-boot (1.2.1.RELEASE) アプリケーションがあります。
次の構成で同時実行制御を正常に実装しました
@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();
}
}
}
2 つの異なるセッションで同じユーザー アカウントを使用してログインしようとすると、現在のユーザーがログアウトするまで、2 回目の試行は失敗します。
これは単一インスタンス環境ではうまく機能しますが、Herkou の複数の dyno にデプロイしたいので、セッションを外部化する必要があります。
spring-session + spring-boot-starter-redis は、これに最適な候補のようです。
spring-session のドキュメントから、アノテーション@EnableRedisHttpSession
を追加してJedisConnectionFactory
.
これは実際に機能し、その注釈を追加すると、セッションが Redis に保存されます。これは、redis-cli を使用して確認できます。
ただし、この注釈を追加すると、同時実行制御が壊れます。
注釈@EnableRedisHttpSession
を追加すると、SessionRegistryImpl
メソッドが呼び出されることはなく、メソッドも呼び出されませんHttpSessionEventPublisher.sessionCreated()/sessionDestroy()
。
これは、現在のユーザーがログアウトすると、そのユーザー名を使用しようとしている他のセッションはログインできず、ログアウトしたばかりのユーザーは再ログインできないことを意味します。これは、セッションが ???registry/repository??? から削除されないためです。
ストアとしてredisを使用しながら、セッションの作成/破棄を機能させる方法についての洞察をいただければ幸いです。