はじめに
こんにちは。Spring 初心者です。
Spring Security を使って Web アプリに認証機能を追加しようとした際に詰まったので、その際に知ったことの備忘録になります。
Spring Security は 6.0 のリリース以降、仕様が大幅に変更になったようです。しかし、ネット上で簡単に調べただけでは古い情報がたくさんヒットしてしまうため、私のような Spring 初心者はもれなく大混乱に陥ります。(はじめから公式を読め)
同様の記事は他にもあるものの、少しでも Spring Security 6.X に関する情報を増やすためにこちらに残しておきます。
ちなみに私が使用した Spring Boot のバージョンは3.5.3
、Spring Security のバージョンは6.5.1
です。
詰まったこと
「Spring Security ってやつを使えば簡単に認証機能を追加できるのね~」とほいほいつまみ出した私は、ネットで調べながらこんな感じでSecurityConfig.java
を書いてみました。
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/admin/**").hasRole("ADMINISTRATOR")
.requestMatchers("/edit/**").hasAnyRole("ADMINISTRATOR", "EDITOR")
.requestMatchers("/view/**").hasAnyRole("ADMINISTRATOR", "EDITOR", "VIEWER")
.anyRequest().authenticated()
)
.formLogin() // deprecated
.permitAll()
.and() // deprecated
.logout() // deprecated
.logoutSuccessUrl("/");
return http.build();
}
}
これ、少なくとも私の環境では一応動くのですが、非推奨のメソッドを使ってるということで IDE に怒られました。
ここから仕様がよくわからないままごちゃごちゃ書き換えて沼りました1が、色々調べた結果次のような形に落ち着きました。
Spring Security 6.X での書き方
package com.example.demo.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.formLogin(login -> login
.permitAll())
.logout(logout -> logout
.logoutSuccessUrl("/"))
.authorizeHttpRequests(authz -> authz
.requestMatchers("/css/**").permitAll()
.requestMatchers("/").permitAll()
.requestMatchers("/admin/**").hasRole("ADMINISTRATOR")
.requestMatchers("/edit/**").hasAnyRole("ADMINISTRATOR", "EDITOR")
.requestMatchers("/view/**").hasAnyRole("ADMINISTRATOR", "EDITOR", "VIEWER")
.anyRequest().authenticated()
);
http.csrf(AbstractHttpConfigurer::disable);
return http.build();
}
}
こちらの記事など23を参考にすると、このような書き方になるようです。
まずは、アノテーションとして@Configuration
と@EnableWebSecurity
の 2 つが必要になります。Spring Security 6.0 以降、@Configuration
も明示的に書く必要があるようです。
記法的には、and()
は使えないという点が大きいです。このためformlogin()
やlogout()
をラムダ式で記述する必要があります。
また、Spring Security 6.X では CSRF 保護の仕様が変わりました。4「ログインしてから POST すると 403 エラーになる…!」という場合はこれが原因かもしれません。私の場合は学習目的の開発でしたので、とりあえずhttp.csrf(AbstractHttpConfigurer::disable)
で CSRF 保護を無効化しました。
Spring Security 6.X では、基本的には上記のように記述すれば標準的な認証機能を実装できるはずです。
まだまだ勉強中ですので、随時追記・修正します!