Spring Securityでフォーム認証を実装する(設定編)ー Spring Security ver 6.0.0以降の場合

SpringSecirityはバージョンごとに設定の書き方が大幅に変更されている。
ここでは、バージョンごとに記載方法が大きく変更となっているJavaConfig の記載方法についてまとめる。

バージョンによらない部分の実装については、下記の記事参照。

olafnosuke.hatenablog.com


@EnableWebSecurityアノテーションを付ける

このクラスに記載の設定を適用したSpringSecurityによるフォーム認証を有効化するために、「@EnableWebSecurityアノテーションをクラスに付与する。

Spring Security ver6.0.0以降では、「@EnableWebSecurity」から@Configurationアノテーションが削除されているので、自分で@Configurationアノテーションを付与する必要がある。

@EnableWebSecurity
@Configuration
public class FormSecurityConfiguration {
}

パスワードのエンコーダクラスをDIコンテナに登録する

作成したJavaConfigクラス内でパスワードのエンコーダクラスをDIコンテナに登録するメソッドを実装する。
使用するエンコーダはプロジェクトの仕様により適切なものを選定する。

/**
 * パスワードのエンコーダーをDIコンテナに登録する。<br>
 */
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

認証の設定を行うメソッドを実装する。

このメソッドでは、以下の設定を実施している。

  • 認証マネージャーの構築
  • 認証の対象とするURLの設定
  • フォーム認証の設定
  • ログアウトの設定
/**
 * {@link SecurityFilterChain}をDIコンテナに登録する。<br>
 * 
 * @param http
 *          {@link HttpSecurity}
 * @return {@link SecurityFilterChain}
 * @throws Exception
 *           セキュリティ設定時に例外が発生した場合
 */
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
}
認証マネージャーの構築

Spring Security ver5.7.0より前では、引数が「AuthenticationManagerBuilder」なconfigureメソッドで設定していた内容である。
パスワードエンコーダーとユーザ情報を構築するサービスを設定した認証マネージャーを構築する。

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
    builder.userDetailsService(new LocalUserDetailService(passwordEncoder()));
    AuthenticationManager manager = builder.build();
}
認証の対象とするURLの設定

フォーム認証の対象とするURL、対象外とするURLを設定する。
静的ファイルのパスやログイン画面のURLを認証対象外となるように設定している。

SpringSecurity6.0以降では、引数なしの「authorizeHttpRequests()」メソッドが非推奨となったので
引数に「org.springframework.security.config.Customizer」を取るメソッドで実装する。

また、URLを指定するのに使用していた「mvcMatchers」メソッドや「antMatchers」メソッドも使用できなくなったため、全て「requestMatchers」メソッドに置き換える。

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
    builder.userDetailsService(new LocalUserDetailService(passwordEncoder()));
    AuthenticationManager manager = builder.build();

    http.authenticationManager(manager)
        .authorizeHttpRequests((auth) -> auth
            // 認証対象外のURL指定(静的ファイル、エラーページ遷移のURL)
            .requestMatchers("/images/**", "/css/**", "/js/**", "/webjars/**", "/authorization/**", "/filter-error").permitAll()
            // ログイン画面のURLも認証対象外とする
            .requestMatchers("/login").permitAll()
            // 上記以外は認証が必要
            .anyRequest().authenticated());
}
フォーム認証の設定

フォーム認証で使用するログイン画面へ遷移するURL、フォーム認証成功後に遷移するURLを指定する。
また、認証成功時にユーザオブジェクトを構築するハンドラーを追加する。

SpringSecurity6.0以降では、引数なしの「formLogin()」メソッドが非推奨となったので 引数に「org.springframework.security.config.Customizer」を取るメソッドで実装する。

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.formLogin((formLogin) -> formLogin
        // フォーム認証のログイン画面のURL
        .loginPage("/login")
        // 認証成功時に遷移するURL
        .defaultSuccessUrl("/")
        // Form認証成功時にユーザオブジェクトを構築するハンドラーを追加する
        .successHandler(new LocalAuthenticationSuccessHandler()));
}
ログアウトの設定

ログアウトURLやログアウト成功時の遷移先URLの設定を行う。
また、ログアウト時にCookieの値やセッションを無効化するよう設定を行う。

SpringSecurity6.0以降では、引数なしの「logout()」メソッドが非推奨となったので 引数に「org.springframework.security.config.Customizer」を取るメソッドで実装する。

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http.logout((logout) -> logout
        // ログアウトのURL
        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
        // ログアウト成功時のURL(ログイン画面に遷移)
        .logoutSuccessUrl("/login")
        // Cookieの値を削除する
        .deleteCookies("JSESSIONID")
        // セッションを無効化する
        .invalidateHttpSession(true).permitAll());
}

最終的に作成されるJavaConfigクラス

import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import jp.co.sample.web.authentication.handler.LocalAuthenticationSuccessHandler;
import jp.co.sample.web.authentication.user.LocalUserDetailService;

/**
 * フォーム認証する際に使用するSpring Securityの定義クラス。<br>
 */
@EnableWebSecurity
@Configuration
public class FormSecurityConfiguration {

  /**
   * パスワードのエンコーダーをDIコンテナに登録する。<br>
   * 
   * @return {@link PasswordEncoder}
   */
  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }

  /**
   * {@link SecurityFilterChain}をDIコンテナに登録する。<br>
   * 
   * @param http
   *          {@link HttpSecurity}
   * @return {@link SecurityFilterChain}
   * @throws Exception
   *           セキュリティ設定時に例外が発生した場合
   */
  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    AuthenticationManagerBuilder builder = http.getSharedObject(AuthenticationManagerBuilder.class);
    builder.userDetailsService(new LocalUserDetailService(passwordEncoder()));
    AuthenticationManager manager = builder.build();

    http.authenticationManager(manager)
        .authorizeHttpRequests((auth) -> auth
            // 認証対象外のURL指定(静的ファイル、エラーページ遷移のURL)
            .requestMatchers("/images/**", "/css/**", "/js/**", "/webjars/**", "/authorization/**", "/filter-error").permitAll()
            // ログイン画面のURLも認証対象外とする
            .requestMatchers("/login").permitAll()
            // 上記以外は認証が必要
            .anyRequest().authenticated());

    // フォーム認証の設定
    http.formLogin((formLogin) -> formLogin
        // フォーム認証のログイン画面のURL
        .loginPage("/login")
        // 認証成功時に遷移するURL
        .defaultSuccessUrl("/")
        // Form認証成功時にユーザオブジェクトを構築するハンドラーを追加する
        .successHandler(new LocalAuthenticationSuccessHandler()));

    // ログアウト処理の設定
    http.logout((logout) -> logout
        // ログアウトのURL
        .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
        // ログアウト成功時のURL(ログイン画面に遷移)
        .logoutSuccessUrl("/login")
        // Cookieの値を削除する
        .deleteCookies("JSESSIONID")
        // セッションを無効化する
        .invalidateHttpSession(true).permitAll());

    return http.build();
  }

}