Spring Boot 認証認可設計で押さえる実務ポイント

Spring Boot認証認可設計でログイン、JWT、ロール権限、API保護を整理する図

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でも、自部署のユーザーだけ閲覧できる場合があります。あるいは、承認はできるが削除はできない、といった細かい権限もあります。

設計対象向いている表現
大きな利用者区分roleADMIN、MANAGER、USER
操作単位の許可permissionUSER_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経験を活かせる案件相談も行っています。今の経験を次の環境でどう伸ばすか、一度整理してみてください。

IaC INP PM PMO PMP UX Webディレクター インフラエンジニア キャリアチェンジ フロントエンドエンジニア