自作の銀行系システムは実際に何が動いているか — 構成・画面・主要コードで一巡する
はじめに
自作の銀行系システムを、設計だけでなく実際に動くところまで作っている。口座を持ち、残高を照会し、入出金や振込をする——という一連が、画面から API、データベースまで通して動く。要件定義から設計までのプロセスは 設計から入る銀行系API構築 にまとめた。
この記事はその続きで、**「実際に何が動いているか」**を、構成・画面・主要コードで一巡する。以降に書くセキュリティや実装の記事は、この一巡を前提にする。細部を毎回説明しなくて済むよう、共通の土台をここに置く。
全体の構成
利用者の画面から、その裏で複数のサービスが役割を分けて動く。画面は直接データベースを触らず、間に立つ層(BFF)が認証を終端し、各サービスへ問い合わせを束ねる。
利用者(ブラウザ / スマホ)
│
▼
┌──────────────────────────────┐
│ BFF:画面の裏で API を束ね、認証を終端する │
└──────────────────────────────┘
│
├─▶ 認証サービス(ログイン・本人確認)
├─▶ 口座サービス(残高・入出金・振込)
└─▶ 通知サービス(取引の通知)
│
各サービスが自分のデータベースを持つ
一枚岩ではなく、認証・口座・通知を別々のサービスに分けている。境界を分けておくと、片方の都合が他方に染み出しにくい。
画面
顧客はブラウザ(React)から利用する。ログインはパスワードではなく、パスキー(FIDO/WebAuthn)だ。

ログインを通ると、ホームに自分の口座と残高が並ぶ。この記事のあとに書くセキュリティの話は、ちょうどこの「自分の口座を操作する」ところが舞台になる。

画面はきれいに動くが、大事なのは裏側だ。誰がログインしているかを確かめ、その人が自分の口座だけを触れるように制御する——ここがこのシステムの背骨になる。
認証と「本人」
ログインが通ると、システムはその人を「本人(principal)」として持ち回る。以降のAPIは、リクエストのたびにこの本人を見て、「この人が、この対象を、していいか」を判断する。
ログイン ─▶ 本人(principal)を確立
│
├─▶ 参照(GET):本人の口座だけを返す
└─▶ 更新(POST):本人の口座だけを操作させる
│
(ここが後のセキュリティ記事の舞台)
ここで大事なのは、「ログインが通った」と「その口座を触ってよい」は別の判断だということだ。前者は認証、後者は認可。ログインした人が、他人の口座まで触れてよいわけではない。
主要コード:参照APIの所有権チェック
残高照会のような参照API(GET)では、この「本人の口座だけ」を早い段階で確立していた。認証で取り出した本人と、対象の口座の持ち主が一致するかを確かめ、違えば断る。
@GetMapping("/accounts/{id}/balance")
public BalanceResponse balance(@PathVariable String id,
@AuthenticationPrincipal Jwt principal) {
String me = principal.getSubject(); // 認証で確立した「本人」
Account account = accounts.findById(id);
// 所有権チェック:対象の口座は、本人のものか?
if (!account.getCustomerId().equals(me)) {
throw new AccessDeniedException("not your account");
}
return BalanceResponse.of(account);
}
短いが、ここに背骨が詰まっている。principal が認証で確立した本人、account.getCustomerId() が口座の持ち主。二つを突き合わせて、一致しなければ触らせない。参照系は、この形で守れていた。
問題は、この「守れていた形」が、更新系(入出金・振込)に自動では引き継がれないことだ——という話は、次の記事に続く。
この記事の位置づけ
ここまでが「このシステムとは何か」の一巡だ。構成(認証・口座・通知の分離)、画面(ログイン・口座操作)、背骨(本人を確立し、所有権で守る)。以降の記事は、この土台の上で、実装で踏んだ落とし穴や設計判断を一つずつ扱う。
関連する記事
- 設計プロセス(要件定義→基本設計→詳細設計)の側は 設計から入る銀行系API構築 にまとめた。
- この口座APIで、参照系では守れていた所有権チェックが更新系に抜けていた話は 口座APIで作りかけたIDOR に続く。
- この銀行に、自作プラットフォームの決済から実際に口座振込を繋いだ話は 自作アプリと自作の銀行を、実際に金が動くまで繋いだ — 決済に口座振込を足し、E2Eで確かめる にまとめた。
- 口座間の振込を、途中で落ちても壊れない分散トランザクションとして作った話は 振込の途中でサービスが落ちても、お金が消えないように — Saga と Outbox で分散した口座間の整合を守る にある。