docker を使ってドメインの異なるサービス間で cookie を共有できるか検証してみました。
環境
構成
sample_apps/ ├── app1/ │ ├── app.py │ ├── static/ │ └── templates/ ├── app2/ │ ├── app.py │ ├── static/ │ └── templates/ ├── certs/ ├── Dockerfile ├── requirements.txt └── docker-compose.yml
mkcert を使用してローカル開発用の証明書を作成
mkcert を使用してローカル開発用の証明書を作成します。
# certs ディレクトリに移動 cd sample_apps/certs # mkcertを使って証明書作成 mkcert -install mkcert localhost
Dockerfile
FROM python:3.12-slim WORKDIR /app COPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txt COPY certs /certs COPY app /app EXPOSE 443 8443 CMD ["python", "app.py"]
docker-compose.yml
version: "3.9" services: app1: build: . container_name: app1 ports: - "8443:8443" volumes: - ./certs:/certs - ./app1:/app app2: build: . container_name: app2 ports: - "443:443" volumes: - ./certs:/certs - ./app2:/app
app
app1
from flask import Flask, render_template app = Flask(__name__) @app.route("/") def home(): return render_template('index.html') @app.route("/view_cookies") def view_cookies(): return render_template('view_cookies.html') @app.route("/delete_cookies") def delete_cookies(): return render_template('delete_cookies.html') @app.route("/sample_client") def sample_client(): return render_template('sample-client.html') if __name__ == "__main__": app.run(host="0.0.0.0", port=8443, ssl_context=( "/certs/localhost.pem", "/certs/localhost-key.pem" ))
app2
from flask import Flask, render_template app = Flask(__name__) @app.route("/") def home(): return render_template('index.html') @app.route("/view_cookies") def view_cookies(): return render_template('view_cookies.html') @app.route("/delete_cookies") def delete_cookies(): return render_template('delete_cookies.html') @app.route("/sample_container") def sample_container(): return render_template('sample-container.html') if __name__ == "__main__": app.run(host="0.0.0.0", port=443, ssl_context=( "/certs/localhost.pem", "/certs/localhost-key.pem" ))
html
cookie を作成・削除するページは省略します。
app1/templates/sample-client.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>sample-client</title> </head> <body> <script> window.addEventListener("message", (event) => { if (event.origin !== "https://example.com") return; console.log("Received data:", event.data); }); function appendIframeContainer() { var sampleContainer = document.createElement('iframe'); sampleContainer.src = 'https://example.com/sample_container'; sampleContainer.style.cssText = 'width: 0px; height: 0px; display: none;'; document.body.appendChild(sampleContainer); } if (document.readyState == 'loading') { document.addEventListener('DOMContentLoaded', appendIframeContainer()); } else { appendIframeContainer(); } </script> </body> </html>
app2/templates/sample-container.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Sender</title> </head> <body> <h1>Sender Page</h1> <script> var data = {'specificCookie': document.cookie}; console.log(data) window.parent.postMessage(JSON.stringify(data), '*'); </script> </body> </html>
アプリ立ち上げ
docker-compose build docker-compose up
環境準備(/etc/hosts)
127.0.0.1 example.com 127.0.0.1 app2.local
cookie 準備
条件
以下の条件でドメインの異なるサービス間で cookie が共有できるか検証します。
- Secure 属性: HTTPS 通信時のみ Cookie を送信
- SameSite 属性: クロスサイトリクエストの制御に利用
cookie 名 | 値 | Secure | SameSite | 備考 |
cookie_01 | sample_01 | 無 | ||
cookie_02 | sample_02 | 有 | ||
cookie_03 | sample_03 | 有 | None |
検証
内容
- 「https://example.com/」 のクッキーを 「https://app2.local:8443/」 で取得できるか確認
検証結果
- SameSite に None を入れないと少なくとも Chrome は cookie は共有できなさそう
- SameSite を None にするには Secure は必須
参考情報
SameSite 属性
空の場合はブラウザによって None だったり Lax だったり。。。
chrome は Lax 扱いで... Firefox と Safari はまだゆるそう。。。
None
全ての cross-site なリクエストに対して Cookie が付与される。
Strict
same-site に対するリクエストにのみ Cookie が付与される。
Lax
None と Strict の間に位置するようなものとのこと。。。
GET リクエストや method=GET のフォームによる画面遷移のようなトップレベルナビゲーションの場合のみ、サイト間通信であっても送信先サイトで設定された Cookie は送信先に渡される。
iframe 経由はダメそう。