daisuzz.log

Spring SecurityをComponent-basedな設定方法で設定してみる

背景

Spring Security without the WebSecurityConfigurerAdapter を見て、従来のSpring Securityの設定方法がSpring Security5.7から非推奨になることを知ったので代わりの設定方法を試してみます。

環境

  • Spring Boot 2.6.7
  • Kotlin 1.6.21

何が変わるのか

Spring Security 5.7からWebSecurityConfigurerAdapterを継承した従来の設定方法が非推奨になります。

WebSecurityConfigurerAdapterを継承した従来の設定方法とは、以下のようにWebSecurityConfigurerAdapterを継承したクラスに@EnableWebSecurityを付与して、configure()メソッドをoverrideしていく方法です。

@EnableWebSecurity
class SecurityConfiguration : WebSecurityConfigurerAdapter() {
    override fun configure(http: HttpSecurity) {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic()
            .and()
            .csrf().disable()
        http.logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/")
    }
}

従来の方法が非推奨になった代わりの方法として、Spring Security5.4から提供されていたcomponent-basedな設定方法を利用することが推奨されます。component-basedな設定方法とは、設定したいコンポーネントをBean定義で設定する方法です。

以下の例はWebSecurityとHttpSecurityをそれぞれ設定した例です。 WebSecurityの設定はWebSecurityCustomizerをBean定義し、HttpSecurityの設定はSecurityFilterChainをBean定義しています。

@Configuration
class SecurityConfiguration {

    @Bean
    fun webSecurityCustomizer(): WebSecurityCustomizer {
        return WebSecurityCustomizer { it.ignoring().antMatchers("/foo.css", "/bar.img") }
    }

    @Bean
    fun filterChain(http: HttpSecurity): SecurityFilterChain {
        http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .and()
            .httpBasic()
            .and()
            .csrf().disable()
        http.logout()
            .logoutUrl("/logout")
            .logoutSuccessUrl("/")
        return http.build()
    }
}

他のSpringのプロジェクトだとBean定義で設定することがメジャーなのに対し、Spring Securityは独特な設定方法を採用していて個人的にも違和感があったので、Bean定義による設定方法が推奨されることはうれしいです。

ちなみに

Spring SecurityはKotlin DSLを提供しているので、↑のサンプルコードのうちHttpSecurityの設定を書き直すと以下のようなコードになります。 何に対してどういう設定をするのかインデントとブロックで見やすくなっています。

    @Bean
    fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
        http {
            authorizeRequests {
                authorize(anyRequest, authenticated)
            }
            formLogin { }
            httpBasic { }
            csrf {
                disable()
            }
            logout {
                logoutUrl = "/logout"
                logoutSuccessUrl = "/"
            }
        }
        return http.build()
    }

実際に動作確認したサンプルコードは以下にあります。

github.com

参考資料

Spring Security without the WebSecurityConfigurerAdapter

Configure HTTP Security without extending WebSecurityConfigurerAdapter · Issue #8804 · spring-projects/spring-security · GitHub

Kotlin Configuration :: Spring Security

Spring Security with Kotlin DSL | Baeldung on Kotlin