403で止まるSpringアプリを設定変更なしでデバッグする――IntelliJ IDEAのSecurity inlay活用術

Java / Spring

403の先にある「本来の不具合」をどう調べるか

Spring MVCのコントローラーやサービスにブレークポイントを置き、HTTPリクエストを送ったのに処理が止まらない。返ってきたのは403 Forbidden、あるいは401 Unauthorizedやログイン画面へのリダイレクト――Spring Securityを使う開発では、よくあるデバッグ上のつまずきです。

このとき問題は、アプリケーションロジックに到達できないことです。SecurityConfigを一時的に書き換えてpermitAll()にしたり、認証用のモックを追加したりすれば先へ進めます。しかし、設定変更には再起動が伴い、デバッグ終了後に変更を戻し忘れるリスクもあります。

この課題に対して、IntelliJ IDEA 2026.2のSpring DebuggerにはSecurity inlayが追加されました。実行中のSpring Security設定をIDEから確認し、デバッグセッション中だけ、指定したHTTPエンドポイントを一時的に認証済みとして扱えます。

実行中のアプリが要求する権限を確認できる

保護されたエンドポイントで最初に知りたいのは、「この実行中のアプリは、実際にどの権限を要求しているのか」です。

Security inlayは、hasRolehasAuthorityに相当するHTTP認可ルールをエンドポイント付近に表示します。複数のSecurityFilterChain、マッチャーの順序、アクティブなプロファイル、条件付きで登録された設定などがある場合でも、ソースコードを読むだけではなく、実行中の設定に基づいて確認できる点が重要です。

ただし、独自のAuthorizationManagerなど、IDEが権限一覧として評価できないルールは、具体的なロールではなく不明なロックとして表示されます。その場合でも、inlayから関連する設定コードへ移動できます。

つまり、この機能はSecurityConfigの代替ではありません。現在のJVMで有効なHTTP認可ルールを確認するための入口として利用するものです。

設定変更なしでエンドポイントを通過させる

権限を確認したら、inlayのUnlock操作から次の2つの方法を選べます。

  • エンドポイントが要求する権限を満たす形で、単純にアンロックする
  • ユーザー名と任意の権限を指定して、特定の認証状態を再現する

単純なアンロックは、認証・認可そのものをテストしたいのではなく、保護された先の処理を調べたい場合に適しています。

  • コントローラーのバインディングや入力処理を確認する
  • 保護されたルートから呼び出されるサービスをデバッグする
  • ローカルの認証設定に阻まれたスモークテストを実行する
  • 認証処理を変更せずに不具合を再現する

一方、カスタム権限を指定する方法は、権限の違いによる分岐を調べる場合に有効です。例えば、ユーザー名をadmin、権限をROLE_ADMINROLE_MANAGERとしてリクエストを再送し、コントローラーや下流サービスの挙動を確認できます。

SecurityContextに何が注入されるのか

Unlockは、SecurityConfigを変更したり、認証フィルターを無効化したりする仕組みではありません。デバッガーが実行中のAuthorizationFilterにフックし、対象リクエストに対してTestingAuthenticationTokenSecurityContextへ追加します。

その後のSpring Securityは、通常の認証済みプリンシパルとして処理します。そのため、次のようなコードは指定したユーザー名や権限を参照できます。

@GetMapping("/active")
ResponseEntity<List<Member>> getAllActive(Principal principal) {
    log.info("Auth Principal Name: {}", principal.getName());
    // ...
}

SecurityContextHolder.getContext().getAuthentication()PrincipalAuthentication型のメソッド引数からも、注入された認証情報を参照できます。また、同じSecurityContextを読むメソッドセキュリティにも影響します。

例えば、HTTPエンドポイントをROLE_ADMINでアンロックした場合、そこから呼び出される次のメソッドは、@PreAuthorizeのチェックも通過できます。

@Service
class UserService {
    @PreAuthorize("hasRole('ADMIN')")
    public User findUser(Long id) {
        // ...
    }
}

ただし、これはUnlockがメソッドセキュリティを直接解除しているわけではありません。メソッドセキュリティのインターセプターが、同じSecurityContextに入った権限を評価しているためです。

@AuthenticationPrincipalや具体的な型には注意

アンロック時のプリンシパルは、アプリケーション固有のUserDetailsではなく、単純なユーザー名文字列をプリンシパルとするTestingAuthenticationTokenです。

そのため、次のような制約があります。

  • @AuthenticationPrincipal付きの引数は解決されず、nullになる既知の問題がある
  • JwtAuthenticationTokenなど具体的な認証トークン型の引数は、型不一致で例外になる可能性がある
  • JWTクレーム、資格情報、セッションに依存する処理は通常のログイン時と同じにならない
  • PrincipalまたはAuthenticationのような基底型で受け取る処理は利用しやすい

したがって、Unlockで確認できるのは「指定した権限を持つ認証済みユーザーが来た場合の処理」です。実際のJWTや独自プリンシパルを含む認証フロー全体を再現する機能ではありません。

Unlockはどこまで有効なのか

Unlockの適用範囲は、エンドポイントのURIとHTTPメソッドに基づきます。例えば、GET /admin/users/42をアンロックしても、次のリクエストまで自動的に許可されるわけではありません。

  • POST /admin/users/42
  • GET /admin/users/99

一方、コントローラーの@GetMapping("/admin/users/{id}")に対応するパターンを対象にした場合は、パターンに一致するIDが対象になります。どの範囲を開けたのかを意識して操作する必要があります。

解除状態はデバッグセッション中だけ有効で、再ロックするか、アプリケーションを再起動すると消えます。Spring Boot DevToolsによる再起動でも解除されます。アプリケーションの設定ファイルやソースコードには、変更内容は保存されません。

最大の注意点:IDEからのリクエストだけではない

最も重要なのは、UnlockがIntelliJ IDEAのHTTP Clientだけに適用されるわけではないことです。実行中のアプリケーションに到達できるクライアントであれば、同じURIとHTTPメソッドのリクエストが影響を受けます。

  • IntelliJ IDEAの.httpファイル
  • ブラウザー
  • curl
  • Postman
  • テストスイート

つまり、ネットワークからアクセス可能な共有環境やステージング環境で不用意にUnlockすると、IDE以外のクライアントからも対象エンドポイントが指定した権限で通過する状態になります。作業後は明示的にロックするか、デバッグセッションを終了してください。

特にリモートJVMでもSecurity inlayは利用できますが、Unlock状態を示すアプリケーションログやActuatorの表示はありません。接続中のIDEでinlayを確認する以外に、状態を把握する手段がない点は、チーム運用上のリスクになります。

CSRFを無効化する機能ではない

Unlockは認証済みのAuthenticationを用意するだけで、Spring Securityのフィルターチェーン全体を停止するものではありません。

そのため、CSRF対策が有効なアプリケーションでは、トークンが必要なPOSTPUTDELETEなどは、認証を通過してもCSRFチェックで拒否される可能性があります。Unlockしたからといって、CSRFトークンまで自動的に付与されるわけではありません。

また、対象はHTTPエンドポイントの認可です。次の領域には直接のinlayやUnlock操作はありません。

  • Spring WebFluxのAuthorizationWebFilter
  • @PreAuthorize@PostAuthorize@Securedそのもの
  • authorizeRequestsFilterSecurityInterceptorを使う古い構成

対応するのは、ServletスタックでAuthorizationFilterauthorizeHttpRequestsAuthorizationManager APIを利用する構成です。WebFluxアプリケーションでは、この仕組みを利用できません。

permitAll()やモック認証との違い

従来のローカル開発では、開発用プロファイルでpermitAll()にしたり、テスト用の認証フィルターを追加したりする方法が一般的でした。しかし、これらはアプリケーションの設定や起動条件を変更します。

Security inlayとの違いは次の通りです。

  • SecurityConfigを書き換えない
  • アプリケーションの再ビルドや再起動が不要
  • 認証を完全に無効化するのではなく、指定した権限で評価を続ける
  • デバッグ終了時に解除状態が消える
  • 特定のユーザー名・権限セットを使った検証ができる

ただし、安全性の面では「IDEだけが通れる一時設定」と考えてはいけません。Unlock後のリクエストは、条件に一致する全クライアントに影響します。利便性と引き換えに、実行中プロセスの認可判断を変える機能だと理解することが重要です。

実務での使い分け

安全に活用するなら、次のような運用が現実的です。

  1. まずinlayで実行中の要求権限と対象URI・HTTPメソッドを確認する
  2. ローカル環境で、必要最小限のエンドポイントだけをUnlockする
  3. 認証情報に依存する処理では、実際のログインやトークンフローとの差分を意識する
  4. CSRFやメソッドセキュリティなど、Unlockの対象外となるチェックを分けて検証する
  5. デバッグ終了時にロック状態を解除し、必要に応じてアプリケーションを再起動する
  6. 共有環境やネットワーク到達可能な環境では、影響範囲を確認してから使う

AIエージェント連携への展望

IntelliJ IDEA 2026.2では、UnlockはIDE上で人間が実行する操作です。外部スクリプトやAIエージェントが自動的に権限を取得してUnlockするためのプログラム上の切り替えは、現時点では提供されていません。

将来のリリースでは、エンドポイントが要求する権限の取得や、ロック・アンロック操作をAIエージェントから行うMCPツールと関連スキルが計画されています。実現すれば、エージェントが一度だけ人間の承認を受けた後、コントローラーやサービスの変更に対してリクエストを繰り返し実行する、といった開発フローが考えられます。

一方で、認可を変更する操作をAIに委ねる場合は、対象URI、HTTPメソッド、権限、解除期間、接続先環境を明示的に制限する仕組みが不可欠です。自動化の便利さだけでなく、誰がいつどの権限でエンドポイントを開けたのかを追跡できる設計も課題になります。

まとめ

Security inlayは、403で止まったSpringアプリケーションを、設定変更や再起動なしで本来の処理まで進めるための実践的なデバッグ機能です。実行中のSecurityFilterChainからHTTP認可ルールを確認し、指定した権限を持つTestingAuthenticationTokenSecurityContextへ注入することで、コントローラーやサービスの動作を検証できます。

ただし、これは単なるIDE内のモックリクエストではありません。UnlockしたURIとHTTPメソッドは、実行中アプリケーションに到達できるすべてのクライアントへ影響します。Servlet限定、CSRFは別途必要、@AuthenticationPrincipalや具体的な認証トークン型には制約がある、といった点も押さえておく必要があります。

認証・認可をテストする機能と、認可に阻まれたロジックをデバッグする機能を使い分けること。 その前提を守れば、Security inlayはSpring Securityの設定を壊さずに、403の先にある不具合へ素早く到達するための有力な選択肢になります。

出典: JetBrains Blog

タイトルとURLをコピーしました