Spring Boot 認可設計でロール権限とリソース所有者チェックを分ける考え方

Spring Boot 認可設計でロール権限とリソース所有者チェックを整理する図

Spring Bootの認可はロールだけでは足りない

Spring Boot 認可 設計でよくある失敗は、ADMINとUSERのようなロールだけで全てを判断しようとすることです。ログイン済みかどうか。管理者かどうか。自分のデータかどうか。これらは同じ認可でも、見るべき情報が違います。

結論から言うと、認可設計では入口の制御、業務データに基づく制御、監査を分けます。URL単位では大きなアクセス制御を行います。一方で、リソース所有者や組織境界はService層で確認する方が自然です。

この記事では、Spring BootでAPIを開発する経験者向けに、ロール権限、リソース所有者、method security、access controlの設計判断を整理します。レビューで見落としやすい失敗例も扱います。

Spring Securityの認可は入口と業務ルールに分ける

まず、Spring Securityの認可は入口を守る仕組みとして使いやすいです。Spring Security公式のAuthorizationでも、認可サービスの考え方が整理されています。

例えば、管理者APIへのアクセスを管理者ロールに限定する。認証済みユーザーだけがマイページAPIを呼べるようにする。こうした制御は、HTTPリクエストの入口で止めるとわかりやすいです。

@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
  return http
      .authorizeHttpRequests(auth -> auth
          .requestMatchers("/api/admin/**").hasRole("ADMIN")
          .requestMatchers("/api/**").authenticated()
          .anyRequest().permitAll()
      )
      .build();
}

ただし、この設定だけでは「自分の注文だけ参照できる」といった条件を表現しにくいです。URLだけでは、対象リソースの所有者がわからないからです。

ロール権限は入口の粗い制御に向いている

ロール権限は、利用者の種類を大きく分けるときに便利です。管理者、一般ユーザー、運用担当、閲覧専用ユーザーのような分類です。

認可の種類見る情報向いている場所
ロール権限利用者の役割SecurityFilterChain、Controller入口
権限コード操作ごとの許可method security、Service
リソース所有者対象データと利用者の関係Service、Domain
組織境界テナント、部署、担当範囲Repository条件、Service
監査誰が何を判断したかログ、監査テーブル

一方で、ロールだけで細かい業務ルールを表すと破綻しやすいです。例えば、ORDER_APPROVER_EAST、ORDER_APPROVER_WEST、ORDER_APPROVER_TEMPのようにロールが増え続けると、変更に弱くなります。

そのため、ロールは入口の粗い制御に使います。細かい操作権限や対象データの範囲は、別の設計要素として持つ方が保守しやすいです。

リソース所有者チェックはService層で判断する

リソース所有者チェックは、対象データを読み込まないと判断できません。例えば、「注文を更新できるのは、その注文の担当者だけ」という条件です。

@Service
public class OrderService {

  public OrderDto updateOrder(Long orderId, OrderUpdateRequest request, LoginUser user) {
    Order order = orderRepository.findById(orderId)
        .orElseThrow(() -> new NotFoundException("order not found"));

    if (!order.isOwnedBy(user.userId()) && !user.hasPermission("ORDER_UPDATE_ALL")) {
      throw new AccessDeniedException("not allowed");
    }

    order.update(request);
    return OrderDto.from(order);
  }
}

この例では、ロールだけでなく注文データとログインユーザーの関係を見ています。ControllerでIDだけを見て判断するより、Service層で業務ルールとして表現した方がレビューしやすくなります。

OWASP API Security Top 10のBroken Object Level Authorizationでも、オブジェクト単位の認可不備が大きなリスクとして扱われています。IDを指定するAPIでは、対象リソースを操作できるかを必ず確認します。

method securityは業務操作の境界を守る

Spring Securityにはmethod securityもあります。公式のMethod Securityでは、@EnableMethodSecurity@PreAuthorizeを使ったメソッド単位の認可が説明されています。

@PreAuthorize("hasAuthority('ORDER_APPROVE')")
public OrderDto approve(Long orderId, LoginUser user) {
  Order order = orderRepository.findById(orderId)
      .orElseThrow(() -> new NotFoundException("order not found"));

  if (!order.canBeApprovedBy(user.userId())) {
    throw new AccessDeniedException("not allowed");
  }

  order.approve();
  return OrderDto.from(order);
}

ここでは、@PreAuthorizeで操作権限を確認し、Service内部で対象データに基づく条件を確認しています。入口と業務ルールを二段に分ける考え方です。

ただし、SpELに複雑な業務ロジックを書きすぎると読みにくくなります。method securityは境界の明示に使い、データ状態を使う細かい判断はServiceやDomainへ寄せる方が実務的です。

Spring Boot 認可設計で避けたい失敗例

失敗例起きる問題見直すポイント
USERロールなら全データを見られる他人のデータ参照につながる所有者、組織、担当範囲を確認する
Controllerだけで認可する別経路からServiceが呼ばれると漏れる業務認可はService層にも置く
ロール名が増え続ける変更時の影響が読めないロール、権限、データ範囲を分ける
認可失敗を404と403で混在させる仕様とログ分析がぶれる外部応答と内部ログの方針を決める
権限変更が即時反映されない退職や異動時にリスクが残るトークン内権限とDB参照の役割を分ける

レビューで見る認可設計チェックリスト

  • 認証済みであることと、操作できることを分けているか
  • URL単位の入口制御とService層の業務認可を分けているか
  • リソースIDを受け取るAPIで所有者チェックがあるか
  • 組織、テナント、担当範囲をwhere条件にも反映しているか
  • 認可失敗時のログに調査できる情報が残るか
  • 権限変更時の反映タイミングが明確か

よくある質問

認可チェックはControllerとServiceのどちらに書くべきですか?

入口の粗い制御はController到達前に行うと扱いやすいです。一方で、対象データの所有者や状態を見ないと判断できない認可はService層で確認します。

ADMINロールがあれば所有者チェックは不要ですか?

要件によります。管理者でも組織境界を越えられない場合があります。また、代理操作や例外操作は監査ログが必要です。ADMINかどうかだけで判断しない方が安全です。

まとめ

Spring Bootの認可設計では、ロール権限だけで完結させないことが重要です。入口の制御、リソース所有者チェック、method security、監査ログを分けて設計します。

  • ロール権限は入口の粗いaccess controlに向いている
  • リソース所有者チェックはService層で業務ルールとして扱う
  • method securityは操作権限の境界を明示するために使う

Spring Boot案件では、認可設計を説明できるエンジニアは信頼されやすいです。単にSpring Securityを設定できるだけでなく、業務ルールとセキュリティを分けて考えられることが評価につながります。

Java/Spring Bootの設計経験を活かせる案件や、認証認可、API設計、ログ設計まで関われる環境を考えている場合は、現在の経験をもとに相談できます。

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