# 付録E 用語集 本書で繰り返し登場する用語を、初出の章への参照とともに解説します。 用語間の関係が見えるよう、関連する用語への相互参照も付記しています。 --- **WSGI(Web Server Gateway Interface)** Python の Web サーバと Web アプリケーション(またはフレームワーク)の間のインターフェースを定義した仕様で、PEP 3333 で規定されています。 アプリケーション側は `application(environ, start_response)` という callable を提供します。処理の流れは次のとおりです。 1. `environ` 辞書からリクエスト情報を取得する 2. `start_response` でステータスとヘッダーを送信する 3. レスポンスボディをバイト列のイテラブルとして返す ```{note} WSGI は**同期処理**を前提としています。そのため、1 つのリクエストが完了するまでそのワーカーは他のリクエストを処理できません。Django(デフォルト構成)や Flask が WSGI アプリケーションとして動作します。 ``` → 2 章、付録 A。 関連:**ASGI**、**worker**、**Gunicorn**、**uWSGI**。 --- **ASGI(Asynchronous Server Gateway Interface)** WSGI の非同期拡張として設計されたインターフェース仕様です。アプリケーションは `async application(scope, receive, send)` という非同期 callable を提供します。 | 引数 | 役割 | |------|------| | `scope` | リクエストのメタ情報を持つ辞書 | | `receive` | クライアントからデータを受信する非同期関数 | | `send` | クライアントへデータを送信する非同期関数 | WSGI との最大の違いは、HTTP に加えて WebSocket やサーバのライフサイクル管理(**lifespan**)も同じインターフェースで扱える点です。FastAPI / Starlette、Django(ASGI 構成)が ASGI アプリケーションとして動作します。 → 3 章、付録 B。 関連:**WSGI**、**event loop**、**Uvicorn**、**lifespan**。 --- **middleware(ミドルウェア)** リクエストがアプリケーション(ビュー)に到達する前、またはレスポンスがクライアントに返される前に、横断的な処理を挟む仕組みです。よく使われる用途は次のとおりです。 - 認証チェック - CSRF 検証 - セキュリティヘッダーの付加 - リクエストログの記録 - CORS 制御 WSGI ミドルウェアは、元のアプリケーション callable をラップする別の callable として実装します。`__init__` で内側のアプリケーションを受け取り、`__call__` でリクエストの前処理 → 内側アプリの呼び出し → レスポンスの後処理を行います。 - **Django** では `settings.MIDDLEWARE` のリストに登録されたクラスがチェーン状に構成されます。リクエストはリストの上から下へ、レスポンスは下から上へ流れます(玉ねぎ構造)。 - **FastAPI / Starlette** では `app.add_middleware()` で追加し、追加順が外側(先に実行される)から決まります。 ```{warning} ミドルウェアの配置順序には意味があります。たとえば Django では `SecurityMiddleware` がリストの先頭に、`SessionMiddleware` が `AuthenticationMiddleware` の前に置かれる必要があります。順序を誤ると、認証が行われる前にセッションが取得できない、HTTPS リダイレクトの前にリクエストが処理されてしまうといった問題が発生します。 ``` → 8 章、14-5 章。 関連:**WSGI**、**ASGI**、**CSRF**、**CORS**。 --- **worker(ワーカー)** アプリケーションサーバがリクエストを処理するために生成する実行単位です。Gunicorn や uWSGI では OS のプロセス(またはスレッド)として実装されており、マスタープロセスが複数のワーカープロセスをあらかじめ生成しておく pre-fork モデルが一般的です。 ワーカー数はサーバの同時処理能力を決定する重要なパラメータです。Gunicorn の公式ドキュメントでは `2 × CPUコア数 + 1` が目安として推奨されていますが、アプリケーションの特性によって適切な値は異なります。 | アプリの特性 | 推奨の対処 | |------------|-----------| | CPU バウンド(計算処理が多い) | ワーカー数を CPU コア数に近づける | | IO バウンド(DB・外部 API 待ちが多い) | スレッドを併用するか、ASGI の非同期処理に切り替える | ```{caution} 各ワーカープロセスは独立したメモリ空間を持つため、インメモリのキャッシュやグローバル変数はワーカー間で**共有されません**。本番環境でデータを共有するには Redis や Memcached などの外部ストアが必要です。 ``` → 7 章、付録 C。 関連:**Gunicorn**、**uWSGI**、**event loop**、**reverse proxy**。 --- **event loop(イベントループ)** 非同期プログラミングにおいて、IO の完了を監視し、準備ができたタスクを順番に実行するランタイム機構です。Python 標準ライブラリの `asyncio` モジュールがデフォルトのイベントループを提供しており、Uvicorn では高速な代替実装である `uvloop`(libuv ベース)を使用できます。 イベントループはシングルスレッドで動作します。`await` で IO 待ちに入ったタスクは中断され、その間に他のタスクが実行されることで、1 つのプロセスで多数の同時接続を効率的に処理できます。 ```{important} `await` せずに長時間 CPU を占有する処理や、同期的なブロッキング IO(`time.sleep`、同期的な DB ドライバなど)をイベントループ内で実行すると、**他の全タスクが停止します**。これが本書で繰り返し強調した「`async def` 内でブロッキング IO を行ってはならない」という原則の理由です。 ``` ブロッキング処理が避けられない場合は、`asyncio.to_thread()` や `loop.run_in_executor()` でスレッドプールに処理を委譲し、イベントループを解放してください。Django の ASGI 対応では、同期ビューが自動的にスレッドプールで実行される仕組みが組み込まれています。 → 6 章、15-2 章。 関連:**ASGI**、**worker**、**Uvicorn**。 --- **reverse proxy(リバースプロキシ)** クライアントとアプリケーションサーバの間に配置され、クライアントからのリクエストを背後のサーバに転送し、レスポンスをクライアントに返すサーバです。nginx や Caddy が代表的な実装です。 リバースプロキシが担う役割は多岐にわたります。 - **TLS 終端**: HTTPS の暗号化・復号を行い、背後のアプリケーションサーバには平文 HTTP で転送する - **静的ファイルの配信**: アプリケーションサーバに負荷をかけずに画像・CSS・JS を直接返す - **リクエストのバッファリング**: 遅いクライアントからのデータを一旦受け取ってからアプリケーションに渡す - **ロードバランシング**: 複数のアプリケーションサーバへのリクエスト振り分け - **レート制限・ヘッダーの付加や書き換え** ```{warning} リバースプロキシが介在する環境では、アプリケーションが受け取る `Host` ヘッダーや接続元 IP、プロトコル(HTTP/HTTPS)がクライアントの実際の情報と異なる場合があります。`X-Forwarded-For`、`X-Forwarded-Proto`、`X-Forwarded-Host` などのヘッダーでこの情報を伝達しますが、これらはクライアントが自由に設定できるため、信頼できるプロキシからのものだけを採用する設定(trusted proxy)が不可欠です。 ``` → 7 章、14-6 章。 関連:**worker**、**Host header**、**X-Forwarded-For**。 --- **lifespan(ライフスパン)** ASGI サーバがアプリケーションの起動時と終了時に送信するイベントプロトコルです。 | イベント | タイミング | アプリケーションの処理 | |---------|-----------|----------------------| | `lifespan.startup` | サーバ起動時 | DB コネクションプールの生成、HTTP クライアントのインスタンス化、キャッシュのウォームアップなど | | `lifespan.shutdown` | サーバ停止時 | コネクションのクローズ、一時ファイルの削除など | 初期化に失敗した場合は `lifespan.startup.failed` を返し、サーバは起動を中止します。 ```{tip} FastAPI では `@asynccontextmanager` と `lifespan` パラメータを使った宣言的な記法が推奨 API として提供されています。`yield` の前が起動処理、後が終了処理に対応します。旧 API の `@app.on_event("startup")` / `@app.on_event("shutdown")` も動作しますが、新規コードでは `lifespan` パラメータの使用が推奨されています。 ``` WSGI にはこの仕組みに相当するプロトコルがなく、Gunicorn では `on_starting` / `on_exit` などのサーバフックで代替します。 → 6 章、付録 B。 関連:**ASGI**、**event loop**。 --- **environ** WSGI において、リクエストの全情報を格納する辞書オブジェクトです。次の 2 種類のキーを含みます。 - **CGI 環境変数に由来するキー**: `REQUEST_METHOD`、`PATH_INFO`、`QUERY_STRING`、`SERVER_NAME`、`SERVER_PORT` など - **WSGI 固有のキー**: `wsgi.input`(リクエストボディを読み取るファイルライクオブジェクト)、`wsgi.errors`、`wsgi.url_scheme` など Django の `WSGIRequest`、Flask / Werkzeug の `Request` は、いずれもこの `environ` 辞書をラップして使いやすいインターフェースを提供するオブジェクトです。 → 2 章、付録 A。 関連:**WSGI**、**scope**。 --- **scope** ASGI において、接続のメタ情報を格納する辞書オブジェクトです。WSGI の `environ` に相当しますが、キー名が整理されています。 - `scope["type"]` が接続の種類(`"http"`、`"websocket"`、`"lifespan"`)を示します - HTTP の場合は `scope["method"]`、`scope["path"]`、`scope["query_string"]`、`scope["headers"]` などが含まれます `environ` と異なり、リクエストボディは `scope` に含まれず、`receive` 関数を通じて非同期に取得します。 → 3 章、付録 B。 関連:**ASGI**、**environ**、**receive / send**。 --- **receive / send** ASGI アプリケーションが引数として受け取る 2 つの非同期関数です。 | 関数 | 役割 | |------|------| | `receive` | クライアントからのデータ(リクエストボディ、WebSocket メッセージ、lifespan イベントなど)をイベント辞書として受信する | | `send` | サーバからクライアントへのデータ(レスポンスヘッダー、レスポンスボディ、WebSocket メッセージなど)をイベント辞書として送信する | HTTP レスポンスは `http.response.start`(ステータスとヘッダー)と `http.response.body`(ボディ)の 2 回の `send` 呼び出しで構成されます。この分離により、ストリーミングレスポンスや Server-Sent Events が自然に実装できます。 → 3 章、付録 B。 関連:**ASGI**、**scope**。 --- **Gunicorn(Green Unicorn)** Python の WSGI アプリケーション向け本番サーバです。pre-fork モデルを採用し、マスタープロセスが複数のワーカープロセスを管理します。ワーカーの生成・監視・再起動、シグナルハンドリング(グレースフルリスタート、設定のリロードなど)に長い実績があり、Python Web アプリケーションのデプロイにおける事実上の標準です。 ```{tip} `-k` オプションでワーカークラスを差し替えることで、ASGI アプリケーション(`uvicorn.workers.UvicornWorker`)やイベントベースの処理(`gevent`)にも対応できます。 ``` → 7 章、付録 C。 関連:**worker**、**WSGI**、**Uvicorn**。 --- **uWSGI** 多機能な WSGI / ASGI サーバです。次のような特徴的な機能を持ちます。 - **uwsgi バイナリプロトコル**: nginx がネイティブにサポートする高速プロトコル - **Emperor モード**: 複数アプリケーションの一元管理 - **豊富なプラグインシステム**: 細かな動作のカスタマイズが可能 ```{caution} Gunicorn と比べて設定項目が多く、細かな制御が可能な反面、設定の複雑さが障壁になることもあります。また、`--die-on-term` のように、コンテナ環境で正しく動作させるために明示的な設定が必要な点にも注意してください。 ``` → 付録 C。 関連:**worker**、**WSGI**、**Gunicorn**。 --- **Uvicorn** ASGI アプリケーション向けの軽量・高速サーバです。`uvloop`(libuv ベースの高速イベントループ)と `httptools`(Node.js 由来の HTTP パーサー)を活用して高いパフォーマンスを実現しています。 - `--reload` オプションによるオートリロード機能は開発時に便利ですが、ファイル監視のオーバーヘッドがあるため本番では使用しません - 本番環境では Gunicorn のワーカーとして動作させる構成(`gunicorn -k uvicorn.workers.UvicornWorker`)が推奨されることが多いです - 小規模なデプロイでは Uvicorn 単体の `--workers` モードでも実用的です → 7 章、付録 C。 関連:**ASGI**、**event loop**、**Gunicorn**。 --- **XSS(Cross-Site Scripting)** 攻撃者が Web ページに悪意のある JavaScript を注入し、そのページを閲覧した他のユーザーのブラウザ上でスクリプトを実行させる攻撃手法です。Cookie の窃取、セッションの乗っ取り、ページ内容の改ざんなどに悪用されます。 対策の基本は、ユーザー入力をレスポンスに出力する際の適切なエスケープ処理です。Django のテンプレートエンジンや Jinja2 はデフォルトで HTML エスケープを行います。 ```{warning} `|safe` フィルタや `Markup()` で明示的にエスケープを無効にした箇所は XSS の脆弱性の原因になります。これらの使用には十分な注意が必要です。 ``` → 14-4 章、14-5 章。 関連:**CSRF**、**エスケープ**。 --- **CSRF(Cross-Site Request Forgery)** ユーザーが認証済みの Web アプリケーションに対して、攻撃者が用意した別サイトから意図しないリクエストを送信させる攻撃手法です。ユーザーのブラウザがセッション Cookie を自動送信する仕組みを悪用します。 対策として、フォーム送信時にサーバが発行したトークンを検証する仕組み(CSRF トークン)が広く使われています。 - **Django**: ミドルウェア(`CsrfViewMiddleware`)とテンプレートタグ(`{% csrf_token %}`)で実装されています - **SPA(Single Page Application)**: Cookie ベースの CSRF トークンと `X-CSRFToken` ヘッダーを組み合わせるパターンが一般的です → 14-5 章、14-8 章。 関連:**XSS**、**middleware**、**Cookie**。 --- **SQL injection(SQL インジェクション)** ユーザー入力が SQL クエリに直接埋め込まれることで、攻撃者が意図しない SQL を実行させる攻撃手法です。データの窃取・改ざん・削除にとどまらず、OS コマンドの実行にまでつながる可能性があります。 対策の基本はパラメータ化クエリ(プレースホルダ)の使用です。Django の ORM や SQLAlchemy は内部でパラメータ化を行うため、ORM を正しく使っている限りリスクは低くなります。 ```{caution} `raw()` や `extra()` で生 SQL を書く場合は、パラメータを明示的にバインドする必要があります。ユーザー入力を文字列結合で SQL に埋め込むことは絶対に避けてください。 ``` → 14-5 章。 関連:**バリデーション**、**サニタイズ**。 --- **SSRF(Server-Side Request Forgery)** 攻撃者がサーバ側のコードに任意の URL へリクエストを送信させる攻撃手法です。内部ネットワークへのアクセス、クラウドメタデータエンドポイント(`169.254.169.254`)の読み取り、ファイアウォール内のサービスへの攻撃などに悪用されます。 ユーザーが URL を入力できる機能(Webhook、画像取得、URL プレビューなど)で発生しやすい脆弱性です。対策としては次のような方法が有効です。 - リクエスト先のホスト名・IP アドレスのホワイトリスト制御 - プライベート IP レンジへのアクセス拒否 - DNS リバインディング対策 → 14-5 章。 関連:**reverse proxy**、**バリデーション**。 --- **CORS(Cross-Origin Resource Sharing)** ブラウザの同一オリジンポリシーを緩和し、異なるオリジン間でのリソース共有を可能にする HTTP ヘッダーベースの仕組みです。サーバが `Access-Control-Allow-Origin` ヘッダーでアクセスを許可するオリジンを指定します。 `PUT`、`DELETE` やカスタムヘッダーを伴うリクエストでは、ブラウザが事前にプリフライトリクエスト(`OPTIONS` メソッド)を送信し、サーバの許可を確認します。 ```{note} CORS はブラウザが強制するセキュリティ機構であり、`curl` やサーバ間通信には影響しません。「curl では動くのにブラウザからは動かない」という問題に悩んだときは、CORS の設定を確認してみてください。 ``` → 14-8 章。 関連:**middleware**、**reverse proxy**。 --- **open redirect(オープンリダイレクト)** アプリケーションのリダイレクト機能を悪用し、ユーザーを外部の悪意あるサイトに誘導する脆弱性です。ログイン後のリダイレクト先(`?next=/dashboard` のようなパラメータ)にユーザーが任意の URL を指定できる場合に発生します。 ```{warning} 対策として、リダイレクト先が自サイト内であることを検証する処理が必要です。Django では `url_has_allowed_host_and_scheme` などのユーティリティが用意されています。外部 URL への無条件のリダイレクトは実装しないようにしましょう。 ``` → 14-5 章。 関連:**バリデーション**。 --- **Host header(Host ヘッダー)** HTTP/1.1 で必須のリクエストヘッダーで、クライアントがアクセスしようとしているホスト名を示します。1 つの IP アドレスで複数のドメインをホスティングする仮想ホスティングに必要です。 ```{warning} この ヘッダーはクライアントが自由に設定できるため、サーバ側で無条件に信頼してはなりません。Django の `ALLOWED_HOSTS` 設定は、受け入れる Host ヘッダーの値をホワイトリストで制限する仕組みです。リバースプロキシが介在する場合は `X-Forwarded-Host` ヘッダーの扱いにも注意が必要です。 ``` → 14-6 章。 関連:**reverse proxy**、**X-Forwarded-For**。 --- **X-Forwarded-For** リバースプロキシが、元のクライアントの IP アドレスを背後のサーバに伝えるために使用する HTTP ヘッダーです。プロキシを経由するとアプリケーションが受け取る接続元 IP がプロキシのアドレスになるため、実際のクライアント IP を知るにはこのヘッダーを参照します。 複数のプロキシを経由する場合はカンマ区切りで IP が追加されます(例: `X-Forwarded-For: client, proxy1, proxy2`)。 ```{caution} このヘッダーはクライアントが自由に設定・偽装できます。信頼できるプロキシの数を設定し、右端から数えて適切な値を採用する必要があります。設定を誤ると IP アドレスの偽装が可能になります。 ``` → 14-6 章。 関連:**reverse proxy**、**Host header**、**X-Forwarded-Proto**。 --- **X-Forwarded-Proto** リバースプロキシが、元のクライアントが使用したプロトコル(`http` または `https`)を背後のサーバに伝えるための HTTP ヘッダーです。TLS 終端をリバースプロキシで行う場合、アプリケーションサーバへの接続は平文 HTTP になるため、アプリケーションはこのヘッダーを見て元のリクエストが HTTPS であったかを判断します。 - **Django**: `SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")` で設定します - **FastAPI / Starlette**: `--proxy-headers` オプションや `TrustedHostMiddleware` で扱います ```{warning} 信頼できないプロキシからのヘッダーを採用すると、HTTPS を前提としたセキュリティ設定がバイパスされる恐れがあります。必ず trusted proxy の設定と合わせて使用してください。 ``` → 14-6 章。 関連:**reverse proxy**、**X-Forwarded-For**。 --- **バリデーション(validation)** 入力データが期待する形式・範囲・型に適合しているかを検証する処理です。クライアントからの入力は常に信頼できないものとして扱い、処理の前に検証します。 | フレームワーク | バリデーションの仕組み | |--------------|----------------------| | Django | フォームクラスとシリアライザ | | FastAPI | Pydantic モデルによる型ベースのバリデーション | ```{important} バリデーションはセキュリティ対策の最前線であると同時に、データ品質を保証するビジネスロジックの一部でもあります。入力の検証は処理の最初に行うことを徹底してください。 ``` → 14-4 章。 関連:**エスケープ**、**サニタイズ**、**型変換**。 --- **エスケープ(escape)** データを特定のコンテキスト(HTML、SQL、URL、JavaScript など)に挿入する際に、そのコンテキストで特別な意味を持つ文字を安全な表現に変換する処理です。たとえば HTML エスケープでは `<` を `<` に、`"` を `"` に変換し、ブラウザがデータをマークアップとして解釈しないようにします。 Django テンプレートと Jinja2 はデフォルトで HTML オートエスケープが有効です。 ```{warning} `|safe` フィルタや `{% autoescape off %}` でエスケープを無効にした箇所は XSS の危険があります。これらの使用は、信頼できるコンテンツにのみ限定してください。 ``` → 14-4 章。 関連:**XSS**、**バリデーション**、**サニタイズ**。 --- **サニタイズ(sanitize)** 入力データから危険な要素を除去または無害化する処理です。エスケープとの違いは次のとおりです。 | 処理 | 内容 | |------|------| | エスケープ | 特殊文字を別の表現に置き換える | | サニタイズ | 危険なタグや属性そのものを取り除く | ユーザーが入力した HTML から `