yamabico-dailylog

SE兼アマチュアピアニストのブログです。

Spring Securityで発生するEvent/Exceptionのハンドリングについて

毎日書くと宣言しておいて危うく二日目で約束破るところだった。。。

今日はSpring Securityを使った実装について書きます。

と言っても今日は調べたところ覚書程度で、
内容アップデートしていこうと思います。(多分別記事にする。)
個人的にここは本当に知っておきたいところ。

1. Spring Securityの認証処理で認証成功・失敗時に発生するイベント

Spring Securityでは認証処理を org.springframework.security.authentication.AuthenticationManagerをimplementsしたクラス(ProviderManagerなど)で行なっています。

この時、認証の成功・失敗でそれぞれ以下のイベントメソッドが実行されます。

* 認証が成功した場合
AuthenticationEventPublisher#publishAuthenticationSuccess

* 認証が成功した場合
AuthenticationEventPublisher#publishAuthenticationFailure

イベントにはorg.springframework.security.core.Authenticationをimplementsしたクラスが格納されています。 また、publishAuthenticationFailureの方にはAuthenticationExceptionクラスを継承したExceptionが格納されます。

このイベントはorg.springframework.context.event.@Eventlistnerでハンドリングすることができ、認証成功・失敗による任意の処理を実装することができます。

2. Spring Security ソーシャルログインでの連携同意拒否をした場合のハンドリング

FB・Googleアカウントを使ったソーシャルログインは、 Spring Security5のOAuth2 Clinetを使用すると簡単に実装することができます。

ソーシャルログインで一つポイントなのが、 ユーザーによっては先方(FB/Google)のサイトで「ログイン認証連携拒否」を選択した場合のケースが考えられます。

この場合どのようにハンドリングするのか調査しました。 結果Spring Securityの処理を定義するクラスで制御が書けることが分かりました。

(実装例環境)

- JAVA 8
- Spring Boot 2.4
- Spring Security 5
  • パターン1: 指定パスのページを表示する
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .and()
                .exceptionHandling()
                .accessDeniedPage("/path-to/access-denied-page.html")
        
        ;
    }
}
  • パターン2: ハンドラークラスを用意し、任意の処理をさせる。

ハンドラークラスについては、 AccessDeniedHandlerインターフェイスをimplementsする必要があります。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .anonymous().disable()
                .authorizeRequests()
                .and()
                .exceptionHandling()
                .accessDeniedHandler(new HogeAccessDeniedHandlerImple())
        
        ;
    }
}

と言うことで今夜は以上です。