Security:信頼境界を重ねる
既存Security教材を残したまま、Spring Boot APIの入力、token転送、エラー処理、秘密、ログという視点から多層防御を学びます。
Java / Spring Bootを入口に、金融システムのService・Repository・Transaction設計を読む。
先に学ぶ内容 — Prerequisite: ソフトウェア工学 / 銀行システム学ぶこと — LEARNING GOALS
このページで学ぶこと
- 認証と認可の責任分担
- 入力・エラー・ログの安全設計
- service roleを持たない最小権限
体験18 · JAVA SECURITY(信頼境界を重ねる)
正しいトークンが届いた後も、確認は続くか確かめよう
まずは予想をひと言。本文を読んだ後、教材内の参照元で実際のJavaコードを確認します。
- 01まず予想する — PREDICT
まずここだけ:思ったことをひと言書く
JavaのAPIが正しい形式のトークンを受け取ったら、その先のデータベースはもうそのトークンを確認しなくてよいでしょうか?
正解でなくて大丈夫です。「〜だと思う」から始めてみましょう。
ヒント1を見る
入口で身分証の「形」を確認することと、金庫室で「入室してよいか」を確認することは、同じ確認でしょうか?
ヒント2を見る
Javaのサービスが強い鍵(service role)を持っていたら、侵害されたときの被害はどう変わるでしょうか?
もっと詳しく:この問いで使う専門用語
- 認証は、あなたが誰かを確認することです。
- 認可は、あなたがその操作をしてよいかを確認することです。
- 最小権限は、必要な処理に必要な権限だけを持たせる考え方です。
日常語で理解する — PLAIN LANGUAGE
まず、ここだけつかむ
Java APIはtoken形式を確認し、呼出者のBearer tokenをPostgRESTへ渡して既存の認可を維持します。
service role鍵を持たず、許可されたRPCを呼ぶ最小権限の経路にしています。
DBエラーやstack traceを外へ出さず、デモOTP表示も既定falseにして情報漏えいを防ぎます。
順番に理解する — DIFFICULT PARTS, STEP BY STEP
難しいポイントを、順番にほどく
専門用語を覚えることより、「なぜ必要か」「このシステムのどこで使うか」を理解することが目標です。
認証と認可
認証は本人確認、認可は操作してよいかの判断です。
ログイン済みでも他人の振込を操作してよいわけではないためです。
tokenをPostgRESTへ渡し、DBがcallerと対象を確認します。
最小権限
必要な処理に必要な権限だけを持たせます。
侵害やバグの影響範囲を抑えるためです。
service roleを保持せず既存RPCを利用します。
安全なエラー
利用者へ必要な情報だけを安定した形で返します。
DB構造やstack traceを攻撃の手掛かりにさせないためです。
RpcErrorMapperとGlobalExceptionHandlerで変換します。
発展 — ADVANCEDもっと詳しく確認する最初の学習では読まなくても問題ありません。仕組みをもっと深く理解したい場合に開いてください。
JavaはBearer tokenの形式を確認し、認可はDBまで引き継ぐ
Javaだけで認可を完結させず、既存のDB防御線を維持しています。UIやControllerを迂回されても、最終処理地点がcallerを再確認します。
- 01ControllerがAuthorizationヘッダーのBearer形式を確認
- 02Gatewayが同じtokenをPostgRESTへ転送
- 03PostgRESTがtokenを検証し利用者を解決
- 04PostgreSQLのauth.uid()・RLS・RPCが権限と業務条件を判断
強い鍵を持たない設計
SupabasePropertiesはrest-urlとpublishable-keyだけを持ちます。service role鍵は保持しません。
強い鍵を持たなければ、Javaサービスが侵害された場合の権限を自動的にゼロにはできませんが、少なくとも全RLSを迂回できる万能資格情報の漏えい範囲を避けられます。
外部へ返す情報を制限する
| 危険 | 現在の防御 |
|---|---|
| 生のDBエラー漏えい | SQLSTATEを既知codeへmapし、未知はINTERNAL_ERROR |
| stack trace漏えい | 内部ログだけに記録し一般文言を返す |
| 振込先情報の改ざん | クライアントから銀行・支店・名義を受け取らずDBで解決 |
| 本番OTP露出 | demo-otp-display-enabledは既定false |
| 詳細なhealth情報 | show-detailsはnever |
requestIdとログの注意点
requestIdは障害調査に必要ですが、Authorization、OTP、個人情報、完全なrequest bodyをログへ出してはいけません。
RequestIdFilterは外部のX-Request-Idを引き継ぎます。運用前には長さ・許可文字・改行除去を定め、ログ注入や過大値を防ぐことが望まれます。これは教材上の実装確認から得られる指摘であり、Javaコードの修正はClaude担当です。
体験学習の続き · LEARNING LOOP
ここまで読めましたか?続けて確認してみましょう
信頼境界の重ね方を読んだところで、教材内の参照元で実際のJavaコードを確認し、自分の言葉で説明してみます。
- 02仕組みを確かめる — CONCEPT CHECK
画面操作なしで、仕組みを確かめる
この仕組みは、Mini Bankの画面には現れません。次のEvidenceとCode Trail、教材本文だけで理解を進めます。
- 03証拠を確認する — EVIDENCE
何を見たか、1つずつ確かめる
Evidence(判断の根拠となる記録)を確認したらチェックします。各項目の「何を見るか」を手がかりにしてください。
画面を開けない項目は、Source Trail(教材の参照元)と教材の説明で確認できます。失敗を実際に起こす必要はありません。
- 04コードの処理経路を追う — CODE TRAIL
コードを書く必要はありません
ここでは「説明されている仕組みが、実際のMini Bankのどこに実装されているか」を確認します。まずは日本語の役割説明を読み、入力した依頼がどこへ渡るかをつかみましょう。コードの全文を読む必要はありません。
まずトークンを確認する入口を見て、次にJavaが持つ権限の範囲を見ます。
教材の参照元を確認する — Source Trail ↓Authorizationヘッダーの形式を確認する入口。認証の最初の関門を探します。
services/payment-service/src/main/java/com/minibank/payment/controller/PaymentController.javaservice role鍵を持たない設定。Javaが保持する権限の範囲を探します。
services/payment-service/src/main/java/com/minibank/payment/config/SupabaseProperties.java - 05自分の言葉で説明する — EXPLAIN
LEVEL 1 — やさしい説明(まずここだけ)
なぜPayment Serviceはservice role鍵を持たない設計になっているのでしょうか? 短い2文を目安に説明してください。
日常語だけで完了できます。専門用語の数や正誤を自動採点するものではありません。
ヒント1を見る
「認証」と「認可」という2つの言葉を使って書いてみましょう。
ヒント2を見る
JavaがDBのエラーをそのまま返さない理由を添えてみましょう。
もっと詳しく:LEVEL 2 — 専門用語を使った説明(任意)
認証と認可、最小権限、安全なエラーの3つを使って、Javaがどのように多層防御を重ねているか説明してみましょう。
挑戦する場合は、上の説明欄に追記できます。追加しなくても完了できます。
説明の確認ポイント — Checkpoint- 認証と認可が別の確認であると説明できる
- Javaが強い鍵を持たないことで被害範囲を抑えていると説明できる
理解を確かめる — CHECK YOUR UNDERSTANDING
3問で理解チェック
答えを頭の中で考えてから、各項目を開いて確認してください。
Q1publishable keyだけなら認可は不要ですか?
必要です。呼出者tokenとDB側のRLS・RPC権限で対象操作を制限します。
Q2未知のDBエラーのmessageをデバッグ目的で返しますか?
返しません。requestIdで内部ログと結び、外部には一般文言を返します。
Q3現在のrequestId処理でレビューすべき点は?
外部値の長さ・文字種・改行を制限し、ログ注入や過大値を防ぐ点です。
完全に暗記する必要はありません。大切な考え方を説明できそうなら押してください。
教材の参照元 — SOURCE TRAIL
根拠と関連教材
CURRENT IMPLEMENTATIONは確認したrepository内の実装です。HISTORICAL IMPLEMENTATIONは導入・修正の履歴で、後続migrationによる再定義があり得ます。RELATED LESSONは教材への案内で、実装の一次Sourceではありません。ASSUMPTIONは仮定、UNKNOWNは未確認を表します。
確認基点: d02eae8914f39cbf06bfe422dc39c71886f82b3e / 2026-09-11。稼働環境への適用確認: UNKNOWN。パス実在の自動検査と、記述した技術的事実の確認は別です。
- 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/controller/PaymentController.javarequireBearerTokenAuthorizationヘッダーの形式境界 - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/config/SupabaseProperties.javaservice roleを持たない設定 - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/error/GlobalExceptionHandler.java安全なエラー応答 - 現在の実装 — CURRENT IMPLEMENTATION
services/payment-service/src/main/java/com/minibank/payment/config/RequestIdFilter.java相関IDとMDC