REST API徹底解説!設計・HTTP基礎・セキュリティまで
この記事は、REST APIの基礎から設計ポイント、HTTPの仕組み、セキュリティまでを詳しく解説します。これからREST APIを学ぶ方、理解を深めたい方の参考になれば幸いです。
参考→Udemy 「REST WebAPI サービス 設計」
REST APIの前に、、、そもそもWebAPIとは?
WebAPI
→Webサービスで提供している機能やデータを外からプログラムが読み取りやすい形で定めた規約またはその実装
できること
第三者が情報を利活用して新たな機能を開発
何が嬉しい??
APIエコノミーによる自サービスの発展
何を公開するか?
自サービスの価値のあるもの全部。
リスク
リソースが圧迫される。
ユーザーが減る。
HTTPリクエストの基本構造
REST APIのリクエストは以下の構造です。
POST https://www.post.japanpost.jp HTTP/1.1//リクエストライン
Host: www.post.japanpost.jp //ヘッダー
Content-Length: 31 //ヘッダー
User-Agent: YourApp/1.0 //ヘッダー
Pref=13&add //ボディ
-
リクエストライン:
POST / URI / HTTPバージョン
- ヘッダー: 追加情報
- ボディ: データの中身(POSTやPUTで使用)
HTTPレスポンスの基本構造
HTTP/1.1 200 OK //ステータスライン
Content-Length: 31 //ヘッダー
Date: (サーバ日時) //ヘッダー
Server: (サーバ情報) //ヘッダー
Cache-Control: (キャッシュ制御) //ヘッダー
Pref=13&add //ボディ
- ステータスライン: バージョン、ステータスコード、理由句
- ヘッダー: 応答に関するメタ情報
- ボディ: 応答の中身(JSONなど)
副作用・冪等性について
- 副作用あり: リソースが変更される操作(例: POST, PUT)
- 副作用なし: データ取得だけ(例: GET)
- 冪等: 何度繰り返しても結果が変わらない操作(例: GET, PUT)
ここからはREST APIについて説明していきます
RESTの主要な制約
-
クライアント/サーバ分離
クライアントはUIや入力処理、サーバはデータ提供に集中。役割を分けることで保守性が高まります。 -
階層化システム
Web → APIサーバ → DB のように、階層ごとに分けて再利用性とセキュリティを高めます。 -
コードオンデマンド (オプション)
サーバからコード(JavaScriptなど)をクライアントに配布して機能を拡張可能。 -
統一インターフェース
- リソースはURIで識別
- 表現を用いた操作(例: JSON, XML)
- 自己記述メッセージ(リクエストだけで意味がわかる)
- HATEOAS(レスポンスに次の操作リンクを含める)
-
ステートレス
各リクエストは独立しており、前のリクエストに依存しません。 -
キャッシュ制御
応答はキャッシュ可能。通信コスト削減やレスポンス高速化に役立ちます。
🚀 REST 設計レベル(Richardson Maturity Model)
レベル | 内容 |
---|---|
0 | HTTP を通信手段に使うだけ |
1 | URI にリソースの概念あり |
2 | HTTP 動詞で操作を表現(GET/POST/PUT/DELETE) |
3 | HATEOAS 実現 |
🌟 URI 設計のベストプラクティス
- 短く入力しやすくする
- 人間が見て理解できる
- 大文字・小文字は混在させない(小文字で統一)
- 単語はハイフンでつなぐ(例:
/user-profiles
) - リソース名は複数形(例:
/users
) - サーバ実装を隠す(×
/users.php
) - Hackable な URI(階層構造で意味が通る)
- ルールを統一する
HTTPメソッドと使い方
メソッド | 用途 |
---|---|
GET | リソースの取得 |
POST | リソースの新規作成 |
PUT | リソースの全更新 |
PATCH | リソースの部分更新 |
DELETE | リソースの削除 |
⚡ HTTP メソッドの適用と使い分け
URI は「リソース」、HTTP メソッドは「リソースへの操作」を表します。
例:
GET /v1/users/123 HTTP/1.1
-
GET
: ユーザー情報を取得 -
PUT /v1/users/123
: ユーザー情報を更新 -
DELETE /v1/users/123
: ユーザー削除
パスパラメータとクエリパラメータの使い分け
用途 | パスパラメータ | クエリパラメータ |
---|---|---|
一意なリソースの特定 | /users/123 |
- |
検索・絞り込み・ページング | - | /users?page=3 |
🚦 HTTP ステータスコード主要例
分類 | コード | 意味 |
---|---|---|
1xx 情報 | 100 Continue | リクエストの一部受領 |
2xx 成功 | 200 OK | 成功 |
201 Created | 新規リソース作成 | |
204 No Content | 成功・応答なし | |
4xx クライアントエラー | 400 Bad Request | リクエスト不正 |
401 Unauthorized | 認証必要 | |
403 Forbidden | 禁止 | |
404 Not Found | リソース不在 | |
429 Too Many Requests | レートリミット超過 | |
5xx サーバエラー | 500 Internal Server Error | サーバ内部エラー |
503 Service Unavailable | 一時的に利用不可 |
📦 データフォーマットと設計方針
XML
<user>
<name>tanaka</name>
</user>
- テキスト形式
- タグ階層・属性が利用可能
- 冗長でデータ量が多め
JSON
{
"user": { "name": "tanaka" }
}
- 軽量で可読性が高い
- JavaScript ベースで現代 API の主流
JSONP
callback({ "user": { "name": "tanaka" } });
- クロスドメイン対応のための古い手法
- 実態は JavaScript コード
データ設計の注意点
✅ エンベロープは使わない
- レスポンスボディ内に余計なヘッダー情報を含めず、純粋にデータのみを返す。
✅ オブジェクトの入れ子は深くしすぎない
- データ量を削減し、クライアントでのパース負荷を軽減する。
- 可読性と保守性を高める。
✅ ページネーション情報の返し方
{
"hasNext": true,
"nextPage": "abc123"
}
APIにバージョンを含めるかどうか
✅ APIにバージョンを含めるメリット・デメリット
メリット
- 特定のバージョンを指定してアクセスできるため、クライアント側で突然エラーが発生しにくい。
- 後方互換性を保ちながら機能追加・修正が可能。
デメリット
- 複数バージョンを並行稼働させる必要があるため、ソースコードやデータベースの管理が複雑になる。
- 保守コストが上がる。
結論
- 広く世間一般に公開するようなサービスであれば、利用者の利便性を考慮して APIバージョンを含めたURL設計 を推奨する。
✅ バージョンの指定場所
方法 | 特徴 |
---|---|
パス(例:/v1/users ) |
最も一般的でわかりやすい方法。URLに明示的に含める。 |
クエリパラメータ(例:/users?version=1 ) |
柔軟だが、バージョンの識別がURLの見た目から分かりにくい。 |
ヘッダー(例:GData-Version: 1 ) |
リクエストヘッダーに含める方法。URLがすっきりするが可視性が低い。 |
✅ バージョンの付け方(セマンティックバージョニング)
- バージョン番号の形式:
メジャー.マイナー.パッチ
(例:1.2.3
)
種別 | 意味 | 例 |
---|---|---|
メジャー | 後方互換性のない変更 | 1.x.x → 2.0.0 |
マイナー | 後方互換性のある機能追加 | 1.1.x → 1.2.0 |
パッチ | 後方互換性のあるバグ修正 | 1.2.1 → 1.2.2 |
おすすめの運用
- 後方互換性がなくなったタイミングでメジャーバージョンを更新。
- マイナー・パッチバージョンで頻繁に管理すると運用コストが増えるため、適切な粒度で運用。
✉ 補足
APIのバージョン管理は、クライアントとサーバ間の契約を安定させるための重要な設計要素です。特にパブリックAPIや長期間利用されるAPIでは慎重な設計が求められます。
OAuth と OpenID Connect の概要
✅ OAuth
- 用途:認可(リソースへのアクセス許可を与える仕組み)
- 特徴:第三者アプリケーションがリソース所有者に代わってAPIを利用する際の認可を行う。
✅ OpenID Connect
- 用途:OAuth(認可)+ 本人情報の取得(認証機能を追加したもの)
- 特徴:OAuthに ID トークン(JWT形式の認証情報)を組み合わせた仕様。
OAuth (Authorization Code フローの例)
登場人物
- サービス:LINE(認可サーバー)
- サードパーティアプリケーション:マッチングアプリ
- ユーザー:あなた(リソースオーナー)
フロー
1️⃣ マッチングアプリで「LINEでログイン」ボタンをクリック
⬇
2️⃣ LINE のログイン画面にリダイレクト
⬇
3️⃣ LINE アカウントでログイン・権限許可
👉「このアプリがあなたの基本情報(名前、メールアドレス)にアクセスすることを許可しますか?」
⬇
4️⃣ 認可コード(ワンタイムのコード)が返される
⬇
5️⃣ 認可コードを用いてアクセストークンを取得
⬇
6️⃣ アクセストークンを使ってユーザー情報を取得 → ログイン完了
OpenID Connect の場合
✅ 5 の段階で以下を取得
- アクセストークン(API呼び出し用)
- ID トークン(JWT形式の認証情報)
JWT(JSON Web Token)
- 読み方:ジョット
-
特徴
- 署名付きで改ざんチェック可能
- URL-safe なデータ
- データの中身は JSON 形式
-
用途
- 認証情報をサーバに保存せず、クライアント側に保持
JWT の構造
ヘッダー
{
"typ": "JWT",
"alg": "ES256"
}
アクセストークンの使い方
アクセストークンは Authorization ヘッダーに含める。
例:
Authorization: Bearer アクセストークン
レートリミット(アクセス制限)
- 対象: APIキー, ユーザID
- 制限例: 10分間で30回まで
- アルゴリズム: Fixed Window, Sliding Log, Sliding Window
💡 レートリミットとは?
APIやWebサービスにおいて、特定のユーザーやシステムからの過剰なリクエスト(短時間に大量アクセス)を制御する仕組みです。
主な目的は以下です:
- サーバのリソースを保護し、安定稼働を維持
- 不正利用・DDoS攻撃などの防止
- 公平なリソース利用の確保
🎯 制限の設定項目
設定対象 | 例 |
---|---|
誰に対して | APIキー単位、ユーザーID単位、IPアドレス単位など |
何に対して | 単一API、機能群、API全体 |
制限回数 | 10回、100回、1000回 など |
単位時間 | 10分、1時間、1日など(= window) |
レートリミットのアルゴリズム種類
🕰 1️⃣ Fixed Window(固定ウィンドウ)
動作イメージ
- 各ウィンドウ(例:10分)ごとにカウントをリセット。
- ウィンドウ内で一定回数を超えたらリクエスト拒否。
例:
「10分間に最大30回まで」という制限。
10分の間に30回超えると、10分の終わりまでブロック。
デメリット
- ウィンドウ境界で急に多くのリクエストが集中すると、短時間に2倍のリクエスト(ウィンドウまたぎで最大60回)が可能になる。
📜 2️⃣ Sliding Log(スライディングログ)
動作イメージ
- 各リクエストのタイムスタンプを記録。
- 「今この瞬間から過去10分間に30回リクエストがあったか?」を都度確認。
メリット・デメリット
✅ 突発的なバーストアクセスを防止できる。
⚠️ 過去リクエストのタイムスタンプをすべて記録する必要があり、ストレージ負担が大きい。
⚖️ 3️⃣ Sliding Window Counter(スライディングウィンドウカウンター)
動作イメージ
- Fixed Window と Sliding Log のハイブリッド。
- 直近のウィンドウ間のカウントを補間し、現在のウィンドウにおけるリクエスト比率を計算。
例:
「今のウィンドウで50%、前のウィンドウで50%」のように比率加算。
スムーズな制限でバースト抑制+ストレージ負担軽減。
メリット
- ストレージの負担を減らしつつ、バーストにも強い。
キャッシュ制御
キャッシュ制御の代表ヘッダー
制御タイプ | ヘッダー |
---|---|
有効期限 |
Expires , Cache-Control
|
検証 |
Last-Modified , ETag
|
セキュリティの重要ポイントと対策
REST APIやWebサービスを設計・運用する上で、以下の脆弱性とその対策は必須です。それぞれの脆弱性がどんな仕組みで悪用されるのか、どう防ぐのかを整理します。
🛡 XSS(クロスサイトスクリプティング)
💡 脆弱性の仕組み
悪意あるユーザーが、正規のWebページに不正なスクリプト(JavaScript等)を埋め込むことで、他のユーザーのブラウザ上でスクリプトが実行されます。
これにより、以下のような被害が発生します:
- Cookieの盗難(ログインセッション乗っ取り)
- フォーム情報の不正送信
- ページ内容の改ざん
✅ 対策
対策方法 | 内容 |
---|---|
レスポンスヘッダーの追加 | ブラウザの防御機能を有効化します。 |
X-XSS-Protection: 1 |
XSSフィルタリング機能を有効化(※一部ブラウザでは非推奨の流れもあり) |
X-Frame-Options: DENY |
他サイトのiframeで自サイトページを読み込ませない |
X-Content-Type-Options: nosniff |
ブラウザによるMIMEタイプの勝手な解釈を防ぐ(IE対策) |
入力値・出力値のエスケープ | 特にHTML、JavaScriptに出力する値はサニタイズする |
🛡 CSRF(クロスサイトリクエストフォージェリ)
💡 脆弱性の仕組み
ユーザーが認証済み状態で別サイトの罠ページを踏むことで、意図しないリクエストが発生します。
例えば、ログイン中に攻撃者サイトの画像タグに仕込まれたリクエストで、「勝手に商品購入」などが実行されます。
✅ 対策
対策方法 | 内容 |
---|---|
トークンによる検証 | フォーム送信にランダムなCSRFトークンを付与し、サーバで一致確認します。例:X-CSRF-TOKEN
|
認証付きAPI設計 |
X-API-Key (システム単位)、Authorization (ユーザー単位)で実行可否を確認 |
🛡 HTTP通信の暗号化(HTTPSの必須化)
💡 脆弱性の仕組み
HTTP通信は平文で流れるため、ネットワーク盗聴や改ざんが可能です。
特にアクセストークン、認証情報、個人情報は簡単に盗まれます。
✅ 対策
- 常時HTTPS化
- HSTS(Strict-Transport-Security)ヘッダーの設定(ブラウザにHTTPS強制を指示)
🌟 SSL・TLS・HTTPSの違い
用語 | 内容 |
---|---|
SSL | 暗号化通信プロトコル(旧仕様、非推奨) |
TLS | SSLの後継であり現在主流の暗号化通信プロトコル |
HTTPS | HTTP + TLS/SSL による暗号化通信 |
🛡 JWT(JSON Web Token)の脆弱性と対策
💡 脆弱性の仕組み
JWTはクライアント側でトークンの中身が確認可能であり、署名の検証が不十分だと改ざんを許してしまうリスクがあります。
例:
{
"typ": "JWT",
"alg": "none",
"aud": "https://api.example.com/"
}
このようにalg: none指定や弱いアルゴリズムの指定により、署名チェックをすり抜ける攻撃が知られています。
まとめ
REST APIは「わかりやすく・拡張性が高く・安全に」設計することが重要です。HTTPの基本やセキュリティ、バージョン管理、キャッシュ制御も含め、全体を意識した設計を心がけましょう。