SpringSecurityとH2コンソールの利用設定
対象
以下の環境を利用し、SpringWebによるWebアプリケーション開発を行う場合が対象となる。
- SpringBoot3.X
- SpringSecurity 6.X
- H2 Database
H2の利用設定
通常、SpringBootでデータベースにH2を利用する場合は、依存関係としてH2を追加し、アプリケーション設定の記載のみで利用が可能となる。
- mavenの場合の
pom.xml
記述
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
- Gradleの場合の
build.gradle
記述
dependencies {
・・・
// H2データベースの依存関係追加
runtimeOnly 'com.h2database:h2'
}
- SpringBootの設定:
application.properties
の場合
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:~/DB名
spring.datasource.username=管理ユーザーID
spring.datasource.password=管理ユーザーパスワード
spring.sql.init.mode=always
spring.h2.console.enabled=true
- SpringBootの設定:
application.yml
の場合
spring:
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:~/DB名
username: 管理ユーザーID
password: 管理ユーザーパスワード
sql:
init-mode: always
h2:
console:
enabled: true
しかし、SpringSecurityを追加したアプリケーションの場合は、上記設定のみではH2コンソールのページ(http://localhost:8080/h2-console )にはアクセスができない。
そこで、まずはSpringSecurity側にH2コンソールのページを管理対象とする必要がある。
SpringSecurityの設定
設定クラスの作成とアノテーション付与
まず、SpringSecurity側で設定クラスを作成する。SpringSecurity6では、特に継承やインターフェースを必要とはしないが、アノテーションとして@Configuration
と@EnableWebSecurity
を付与し負ければならない。
今回は設定クラスをSecurityConfig
という名前で作成する。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
}
セキュリティフィルターの作成
セキュリティ設定クラス内では、セキュリティフィルターをメソッド定義することにより、認証や認可内容を追加することが可能となっている。
セキュリティフィルターを指定するメソッドには、以下の内容が必要となっている。
- 戻り値:
org.springframework.security.web.SecurityFilterChain
- 引数:
org.springframework.security.config.annotation.web.builders.HttpSecurity
- 例外:
Exception
の送出 - DI登録:メソッドへ
@Bean
アノテーションの付与
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.web.SecurityFilterChain;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.config.Customizer;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain
securityFilterChain(HttpSecurity http) throws Exception {
}
}
SpringWeb管理外URLの設定
まず、/h2-console
へのパスはSpringSecurityの認証を不要とする設定を行うため、引数のHttpSecurity
オブジェクトに対し認可設定(authorizeHttpRequests()
)を追加する。
また、H2コンソールはSpringMVCの管理外である。(H2Console用のコントローラなどをSpringWeb内で作成することがない)
そのため、requestMatchers()
メソッドの引数にはAntPathRequestMatcher
を使用する必要がある。
以下が、H2コンソールを認証不要とする設定の例である。
@Bean
public SecurityFilterChain
securityFilterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
auth -> auth
.requestMatchers(
AntPathRequestMatcher.antMatcher("/h2-console/**")).permitAll());
・・・
return http.build();
}
CSRFトークン
H2コンソールではCSRFトークンを生成しないが、SpringSecurityではPOSTメソッドは全てCSRFトークンを必須としている。そのため、H2コンソールではCSRFを利用しないように ignoringRequestMatchersの設定が必要となる。
@Bean
public SecurityFilterChain
securityFilterChain(HttpSecurity http) throws Exception {
・・・
http.csrf(
csrf -> csrf
.ignoringRequestMatchers(
AntPathRequestMatcher.antMatcher("/h2-console/**")));
・・・
return http.build();
}
セキュリティヘッダー
H2コンソールでは、セキュリティヘッダーが付与されていると使用できなくなる。そのため、H2のパス内ではセキュリティヘッダーを利用不可とする。
(訂正)公式サイトでは自サイトからであれば読み込み可能とする指定を推奨しているようなので、frameOptionのsameOrigin()を使用するよう変更。
@Bean
public SecurityFilterChain
securityFilterChain(HttpSecurity http) throws Exception {
・・・
http.headers(headers -> headers.frameOptions(
frame -> frame.sameOrigin()));
・・・
}
セキュリティヘッダーやCSRFトークンの設定など、H2コンソール以外では、利用可能としたい。そのため、最終的にはsecurityMatcher()
を使ってエンドポイントの設定などを実施する。
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.securityMatcher(AntPathRequestMatcher.antMatcher("/h2-console/**"))
.authorizeHttpRequests(authz -> authz
.requestMatchers(AntPathRequestMatcher.antMatcher("/h2-console/**")).permitAll())
.csrf(csrf -> csrf
.ignoringRequestMatchers(AntPathRequestMatcher.antMatcher("/h2-console/**")))
.headers(headers -> headers.frameOptions(
frame -> frame.sameOrigin()))
.securityMatcher("/**")
.formLogin(Customizer.withDefaults())
.csrf(Customizer.withDefaults())
.headers(Customizer.withDefaults())
.authorizeHttpRequests(authz -> authz.anyRequest().authenticated());
return http.build();
}
}
ソースコードはGitHubにて公開しています。
Discussion