同時ログイン禁止(後勝ち)

実装

Spring Web Applicationで同時ログイン禁止(後勝ち)を実装するためには、WebSecurityConfigurerAdapterで以下の記述をする。

Spring Security 使い方メモ セッション管理 - Qiita

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().antMatchers("/", "/home").permitAll().anyRequest().authenticated()
            .and().formLogin()
                .loginPage("/login").permitAll()
            .and()
                .logout().permitAll()
            .and()
                .sessionManagement().maximumSessions(1)
                .maxSessionsPreventsLogin(false)
                .expiredSessionStrategy(new MySessionInformationExpiredStrategy());
    }
}
public class MySessionInformationExpiredStrategy implements SessionInformationExpiredStrategy {

    @Override
    public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
        DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
        redirectStrategy.sendRedirect(event.getRequest(), event.getResponse(), "/login");
    }
}

動作

  1. ブラウザAでログイン
  2. ブラウザBでログイン
  3. ブラウザAでログイン後ページを更新 ブラウザAはログイン画面に遷移する。

ただし、ブラウザのタブで同時ログインした場合は、同じセッションIDを使い回すので、この方法ではできない。

java – Spring Securityで複数のブラウザタブを管理できますか? - コードログ

また、UsernamePassword認証をカスタマイズしている場合、UsernamePassword認証のFilterの方が先に実施されるため、この方法(セッション管理)は期待通りの動きにならない。

UsernamePassword認証Filterより前に実行されるようにできれば良いのだが...。

以下はMySessionInformationExpiredStrategyが実行されている場合のスタックトレースf:id:unokun3:20190519090523p:plain