ログイン成功後にXXXを実行したい
- ログイン成功後、ユーザー情報のログを出力したい
- ログイン成功後、〇〇を満たすユーザーはXXにリダイレクトしたい
こうした要望をSpring Securityを使って実装するための方法を紹介します。
私の調べた限り、AuthenticationSuccessHandlerとAuthenticationSuccessEventの2種類の実装方法が存在しました。
versions
- Spring Boot 3.2.3
- Spring Security 6.2.2
AuthenticationSuccessHandler
まずはAuthenticationSuccessHandlerを継承したカスタムのハンドラクラスを作成します。
@Component
public class CustomLoginSuccessHandler implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(final HttpServletRequest request, final HttpServletResponse response,
final Authentication authentication) throws IOException, ServletException {
response.sendRedirect("/");
}
}
そして、Spring SecurityでおなじみのSecurityConfigのsecurityFilterChainの中でsuccessHandlerメソッドを使って先ほどのハンドラをセットします。
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final CustomLoginSuccessHandler customLoginSuccessHandler;
@Bean
public SecurityFilterChain securityFilterChain(final HttpSecurity http) throws Exception {
http //
.oauth2Login(oauth2Login -> oauth2Login//
.loginPage("/oauth2/authorization") //
.successHandler(customLoginSuccessHandler)//
);
return http.build();
}
}
こうすることで、Spring Securityによる認証が成功した後にsuccessHandlerで指定したcustomLoginSuccessHandlerの処理が呼び出されることになります。
AuthenticationSuccessEvent
AuthenticationSuccessEventはアプリケーションでの認証成功を検知し起動するイベントです。
認証失敗を検知するAuthenticationFailureEventも存在します。
@Component
@Slf4j
public class AuthenticationEvents {
@EventListener
public void onSuccess(AuthenticationSuccessEvent success) {
log.info("Authentication is succeeded.");
}
}
注意点として、onSuccessメソッドの中ではSecurityContextHolder.getContext().getAuthentication()がnullを返します。
これは、SecurityContextHolderに認証オブジェクト(Authentication object)がセットされる前にonSuccessが呼ばれていることを意味しています。
また、AuthenticationEventsではリダイレクトなどのHTTPレスポンスを直接いじるような処理は実装できず、そうした処理はAuthenticationSuccessHandlerで実装するのがbetterです。
参考