Spring Bootの認証認可は責務を分けて考える
Spring Bootの認証認可設計で迷う場面は、実務ではかなり多いです。ログイン処理をどう作るか。JWTをどこで検証するか。管理者だけが使えるAPIをどう守るか。こうした判断は、Spring Securityの設定だけでは決まりません。
結論から言うと、認証認可設計では責務の分離が重要です。「誰かを確認する処理」と「何を許可するかの判断」を分けます。さらに、URL単位の保護と業務ルール上の権限制御も分けて考えます。
この記事では、Spring BootでAPIを開発するエンジニア向けに解説します。認証と認可の違い、JWT、ロール権限、API保護を整理します。さらに、レビューで見られやすいポイントも扱います。
Spring Securityでは認証と認可を分けて理解する
まず、認証と認可は別の責務です。認証は「利用者が誰か」を確認することです。一方で、認可は「その利用者に操作を許可するか」を判断することです。
Spring Security公式のAuthenticationでは、認証方式が整理されています。ユーザー名とパスワード、OAuth 2.0 Login、SAMLなどです。つまり、認証方式はアプリケーションの前提によって変わります。
一方で、認可はログイン後の制御です。Spring Security公式のAuthorizationでも説明されています。認証方法に関係なく、認可サービスを利用できるという考え方です。
| 分類 | 見ること | 例 |
|---|---|---|
| 認証 | 誰なのか | ログイン、JWT検証、セッション確認 |
| 認可 | 何を許可するか | 管理者だけ登録できる、本人だけ変更できる |
| 監査 | 誰が何をしたか | 操作ログ、失敗ログ、権限変更履歴 |
実務では、この3つを混ぜると設計が崩れやすくなります。例えば、ログイン処理の中で業務権限まで判断すると、後からAPIごとの制御を変えにくくなります。
API保護はURL単位と業務ルール単位に分ける
次に、API保護はURL単位の制御と業務ルール単位の制御を分けます。URL単位の制御では、ログイン済みか、管理者ロールを持つか、といった大きな入口を守ります。
Spring Security公式のAuthorize HttpServletRequestsでは、HTTPリクエストの認可が説明されています。例えば、管理画面配下だけ特定の権限を要求できます。
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
return http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/admin/**").hasRole("ADMIN")
.requestMatchers("/api/**").authenticated()
.anyRequest().permitAll()
)
.build();
}
ただし、URL単位の制御だけでは足りません。例えば、「注文を更新できるのは、その注文の担当者だけ」という条件があります。このような業務ルールは、Service層やメソッド単位の認可で扱う方が自然です。
Spring Boot 認証認可設計ではJWTの役割を限定する
JWTを使う場合、トークンに何を入れるかで設計が大きく変わります。JWTは「本人確認済みであること」を示す材料です。一方で、すべての業務権限をJWTだけで完結させると、変更に弱くなることがあります。
Spring Security公式のOAuth 2.0 Resource Server JWTでは、JWT構成が説明されています。Resource ServerがBearer Tokenを受け取ります。そして、署名やissuerなどを検証します。
実務では、JWTにユーザーID、tenant ID、scope、roleなどを入れることがあります。ただし、頻繁に変わる権限を詰め込みすぎると問題が起きます。細かい業務条件も同じです。トークンの有効期限中に権限変更が反映されにくくなるためです。
| JWTに入れやすい情報 | 注意したい情報 |
|---|---|
| ユーザーID | 頻繁に変わる細かい業務権限 |
| tenant ID | 個人情報や機密情報 |
| 大まかなroleやscope | 即時反映が必要な停止状態 |
| 有効期限 | 大きすぎる権限リスト |
そのため、JWTは入口の認証情報として扱います。業務上の細かい認可は、DBや権限管理テーブルを参照して判断する設計も検討します。
ロール権限だけで認可設計を完結させない
認可設計でよくある失敗が、ADMINやUSERのようなロールだけで全てを表そうとすることです。ロールは便利ですが、業務上の権限を表すには粗すぎることがあります。
例えば、同じMANAGERでも、自部署のユーザーだけ閲覧できる場合があります。あるいは、承認はできるが削除はできない、といった細かい権限もあります。
| 設計対象 | 向いている表現 | 例 |
|---|---|---|
| 大きな利用者区分 | role | ADMIN、MANAGER、USER |
| 操作単位の許可 | permission | USER_READ、USER_DELETE |
| データ範囲 | scopeや条件 | 自部署のみ、自分のデータのみ |
つまり、ロールは大分類として使い、操作権限やデータ範囲は別に設計します。特に業務システムでは、「誰がどのデータに何をできるか」を言語化してから実装することが重要です。
認可ルールはControllerだけに閉じ込めない
Controllerで権限チェックを書くと、実装は分かりやすく見えます。しかし、同じ業務処理を別のAPIやバッチから呼ぶ場合、チェック漏れが起きやすくなります。
@PostMapping("/orders/{id}/approve")
public void approve(@PathVariable Long id) {
orderService.approve(id);
}
このAPIを管理者だけに制限するなら、URL単位の認可で守れます。一方で、「自分の担当注文だけ承認できる」という条件もあります。その場合は、Service層で注文データと利用者情報を見て判断する必要があります。
そのため、Spring Bootの実務では、入口の認可と業務認可を分けます。入口では未ログインや明らかな権限不足を止めます。業務認可では、対象データを見て許可するかどうかを判断します。
認証認可で避けたいアンチパターン
実務レビューでは、次のようなSpring Boot認証認可設計を見つけたら注意します。
| アンチパターン | 起きやすい問題 | 見直すポイント |
|---|---|---|
| 認証と認可を混ぜる | 責務が曖昧になる | 本人確認と許可判断を分ける |
| JWTに権限を詰め込みすぎる | 権限変更が反映されにくい | 細かい認可はDB参照も検討する |
| Controllerだけで権限チェックする | 別経路から呼ばれたときに漏れる | Service層やメソッド認可も検討する |
| ADMINロールだけで設計する | 業務権限が粗くなる | permissionやデータ範囲を分ける |
| エラー内容を詳しく返しすぎる | 攻撃者に情報を与える | ユーザー向け文言と監査ログを分ける |
もちろん、小さな社内ツールではシンプルなロール制御で十分なこともあります。ただし、利用者やデータ範囲が増える場合は、最初から責務を分けておく方が安全です。
実務で見るSpring Boot認証認可設計のチェックリスト
- 認証と認可の責務を分けているか?
- URL単位の保護と業務ルール上の権限制御を分けているか?
- JWTやセッションに入れる情報を最小限にしているか?
- ロール、permission、データ範囲を混ぜていないか?
- 権限変更をどのタイミングで反映するか決めているか?
- 認可エラー、認証エラー、業務エラーを分けて返しているか?
- 失敗ログや権限変更履歴を監査できるか?
- フロントエンドの表示制御だけに頼っていないか?
まずは、このチェックリストで認証認可の責務をそろえます。そのうえで、Spring Securityの設定を整理します。Service層の業務認可、監査ログも分けて設計すると、レビューしやすくなります。
Spring Boot認証認可設計でよくある質問
Spring BootでJWTとセッションはどちらを使うべきですか?
API中心でフロントエンドと分離しているなら、JWT構成が選ばれることがあります。OAuth2 Resource Server構成も選択肢です。一方で、サーバーサイドレンダリングや管理画面ではセッションが自然な場合もあります。どちらが正解かではありません。運用、失効、権限変更、連携先を見て選びます。
認可はControllerとServiceのどちらで見るべきですか?
入口の制御はController手前で見ると分かりやすいです。ただし、対象データを見ないと判断できない業務認可はService層で扱う方が自然です。つまり、URL単位の認可と業務ルール単位の認可を分けます。
フロントエンドでボタンを非表示にすれば認可になりますか?
なりません。フロントエンドの表示制御はユーザー体験のための補助です。API側で認可しなければ、直接リクエストされたときに不正操作を防げません。そのため、画面制御とサーバー側の認可は両方必要です。
まとめ:Spring Boot認証認可設計は境界を決める設計である
Spring Boot認証認可設計では、ログイン処理だけを考えても不十分です。認証、URL単位の認可、業務ルール上の認可、監査ログを分けて考える必要があります。
まずは、認証と認可の違いをチーム内でそろえます。次に、JWTやセッションに何を持たせるかを決めます。さらに、ロール、permission、データ範囲を分けて整理します。この流れを守ると、変更に強い認証認可設計に近づきます。
Java/Spring Bootの実務では、API設計、例外処理、認証認可、SQL設計がつながります。bluenaの採用情報では、Spring Boot経験を活かせる案件相談も行っています。今の経験を次の環境でどう伸ばすか、一度整理してみてください。
一度カジュアル面談をしませんか?
株式会社bluenaは「高還元」と「伴走支援」を両立したSES企業です。単価の81〜86%を還元する報酬体系と、専任サポーターによる隔週1on1で、エンジニアが納得できるキャリアを実現します。
まとまっていなくてもOK——まずは現在地を聞かせてください。
カジュアル面談ですので、お気軽にお聞かせください。





