この章では、Spring Security を入れた API を小さくテスト駆動で組み立てます。
learn-go-with-tests の HTTP handler の発展として、Java / Spring Boot では「認証と権限」を MockMvc で固定する練習に置き換えます。
- 認証前提の API 契約を
MockMvcで固定する - 未認証の
401と権限不足の403を区別する - 認可ルールを
SecurityFilterChainに集める - ビジネスロジックを Controller や Security 設定から分離する
GET /security/profile- 未認証なら
401 - 認証済みならユーザー名と権限を返す
- 未認証なら
POST /security/admin/reportsADMIN権限がなければ403ADMIN権限があれば201
SecureApiControllerTest.java では、次の 4 つを最初に固定します。
- 未認証のプロフィール取得は
401 - 認証済みユーザーはプロフィールを取得できる
- 一般ユーザーは管理 API で
403 - 管理者ユーザーは管理 API を実行できる
MockMvc に対して .with(user(...)) や .with(httpBasic(...)) を付けると、Security を含む HTTP 契約をコントローラテストで直接確認できます。
セキュリティ設定は SecurityConfiguration.java にまとめます。
authorize.requestMatchers("/security/profile").authenticated();
authorize.requestMatchers("/security/admin/**").hasRole("ADMIN");
authorize.anyRequest().permitAll();この教材では既存の章を壊さないため、CSRF は無効化しています。フォームベースではなく、ステートレスな JSON API の最小構成として扱っています。
Controller は認証情報を直接処理し込みません。
Controller の責務は薄く保ちます。
Authenticationを受け取る- リクエストをサービスへ渡す
- HTTP ステータスを返す
- Spring Security を入れると、アプリ全体に影響が及ぶ
- そのため、認可ルールを限定した
SecurityFilterChainを最初に明示する価値が高い 401と403は意味が違うので、テストで分けて固定する- Security のテストでも、Controller の外へ業務ロジックを逃がしておくと見通しが良い
@PreAuthorizeを使ったメソッド単位の認可- JWT ベースの Resource Server テスト
- CSRF を有効にしたフォーム送信やブラウザ向け API のテスト