Cookieの保存範囲と削除
curlのCookie保存ファイルを使い、同じCookieを別パス・別ホストへ送った結果を確認します。名前が同じCookieの更新、削除時に必要な範囲指定、セッションCookieの扱いまでを続けて操作します。hosts.confには演習用ホスト名と接続先の対応を設定しています。
説明
Cookieは配信側がSet-Cookieで保存を求め、後の要求でクライアントがCookieヘッダーに付ける名前と値です。保存した全Cookieを毎回送るのではなく、宛先のホスト、パス、有効期限などの条件によって選びます。
curlのCookie保存ファイルを使い、同じCookieを別パス・別ホストへ送った結果を確認します。名前が同じCookieの更新、削除時に必要な範囲指定、セッションCookieの扱いまでを続けて操作します。hosts.confには演習用ホスト名と接続先の対応を設定しています。
1二つのCookieを受け取る
shop.example.testから、ホストだけに属するthemeと、example.test配下へ送るlangを受け取ります。
curl -K hosts.confホスト名と接続先の設定 -sS -i -c cookies.txt受信Cookieを保存 http://shop.example.test:18080/setSet-Cookieは二行です。themeにはDomainがなく、受け取ったshop.example.testだけに送るhost-only Cookieになります。langはDomain=example.test、Path=/shop、Max-Age=3600で、対象サブドメインとパス、有効期間を指定しています。
2保存された属性を確認
保存ファイルから宛先・パス・期限の有無を表示します。
python3 jar.pyCookie保存ファイルの属性を表示themeのsubdomainsはFALSE、langはTRUEです。persistentは期限付きかどうかを示します。Cookieの値と属性は別で、langの値はjaです。DomainやPathの文字列まで値の一部になるわけではありません。
3対象パスへ送信
保存ファイルを-bで読み込み、/shop/itemsへ要求します。
curl -K hosts.conf -sS -b cookies.txt保存済みCookieを読み込む http://shop.example.test:18080/shop/items/shop配下の要求受信側のcookieにはlang=jaとtheme=lightが届きます。要求のCookieヘッダーには名前と値が入り、Domain・Path・Max-Ageの属性は送りません。属性はクライアントが送信可否を選ぶために使います。
4似ているパスでも境界がある
/shoppingへ要求します。
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shopping/shopとは異なるパス境界themeだけが届きます。Path=/shopは/shopそのものと/shop/配下には一致しますが、単に文字列の先頭が似ている/shoppingには一致しません。Pathは送信範囲の選択であり、同じサイト内のスクリプトを隔離する安全境界ではありません。
5別のサブドメインへ要求
api.example.testの/shop/itemsを取得します。
curl -K hosts.conf -sS -b cookies.txt http://api.example.test:18080/shop/items同じ親ドメインの別ホストDomain=example.testのlangだけが届き、host-onlyのthemeは届きません。Domainを指定すると、指定ドメイン自身とそのサブドメインが対象になります。先頭のドットには現在のCookie仕様で特別な意味はありません。
6末尾が似ている無関係のホスト
notexample.testへ要求します。
curl -K hosts.conf -sS -b cookies.txt http://notexample.test:18080/shop/itemsラベル境界が一致しないホストCookieは空です。example.testという文字列が末尾にあればよいのではなく、ドメイン名のラベル境界で一致する必要があります。notexample.testはexample.testのサブドメインではありません。
7無関係のDomainを保存しようとする応答
shop.example.testからDomain=other.testを設定する応答を受け取り、保存一覧を開きます。
curl -K hosts.conf -sS -i -b cookies.txt -c cookies.txt既存Cookieを読み込み更新して保存 http://shop.example.test:18080/reject無関係のDomainを指定する応答
python3 jar.py保存されなかったことを確認応答にはbad=yesがありますが、保存一覧には追加されません。応答元shop.example.testはother.testへ一致しないためです。任意のサイトが無関係のドメインのCookieを設定できる仕組みではありません。
8同じ範囲のCookieを更新
themeをdarkへ変更する応答を受け取り、/shop/itemsへ再送します。
curl -K hosts.conf -sS -b cookies.txt -c cookies.txt http://shop.example.test:18080/update同じ範囲のthemeを更新
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/items更新後の値を送信themeはlightからdarkに置き換わります。同じ名前・ドメイン・パスの組合せでは新しい値が以前の値を置換します。同じ名前でもパスが異なるCookieは併存できるため、名前だけでは保存項目を特定できません。
9異なるPathで削除を指示
langをMax-Age=0で削除しますが、ここではPath=/を指定した応答を受け取ります。
curl -K hosts.conf -sS -i -b cookies.txt -c cookies.txt http://shop.example.test:18080/delete-wrongPath=/で削除を指定
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/items元のlangが残ることを確認lang=jaは残っています。元はPath=/shopで保存されているため、Path=/の削除指示は同じ保存項目を指しません。Cookieを消す場合も、保存した範囲と一致させる必要があります。
10元のDomainとPathで削除
Domain=example.test、Path=/shop、Max-Age=0の応答を受け取ります。
curl -K hosts.conf -sS -i -b cookies.txt -c cookies.txt http://shop.example.test:18080/delete元の範囲を指定して期限切れにする
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/items削除後の要求今度はlangが消え、theme=darkだけが届きます。Max-Ageが0以下なら期限切れにします。期限の指定にはExpiresもありますが、両方ある場合はMax-Ageが優先されます。
11セッションCookieを読み込まない起動
保存ファイルのセッションCookieを捨てて開始するcurlの-jを指定します。
curl -K hosts.conf -sS -jセッションCookieを保存ファイルから読み込まない -b cookies.txt http://shop.example.test:18080/shop/itemsthemeには期限がなく、セッションCookieとして保存されていたため、-jでの読込み対象から外れてCookieが空になります。これはcurlの新規セッションの扱いです。ブラウザではセッション復元機能によってセッションCookieが復元される場合があり、終了時の削除を秘密情報の保護策として頼り切らないようにします。
まとめ
Set-Cookieの属性で保存・送信範囲を決め、要求では名前と値をCookieヘッダーへ入れます。
Domainはホスト範囲、Pathはパス境界、有効期限は保存期間に関わります。
更新・削除では名前だけでなくドメインとパスの組合せを一致させます。
操作履歴と解説を振り返れます。
シェル / curl・HTTP/1.1
curl -K hosts.conf -sS -i -c cookies.txt http://shop.example.test:18080/setHTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 28
Cache-Control: no-store
Set-Cookie: theme=light; Path=/
Set-Cookie: lang=ja; Domain=example.test; Path=/shop; Max-Age=3600
{"stored":"theme and lang"}python3 jar.pylang=ja domain=.example.test subdomains=TRUE path=/shop persistent=True theme=light domain=shop.example.test subdomains=FALSE path=/ persistent=False
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/items{"host":"shop.example.test","path":"/shop/items","cookie":"lang=ja; theme=light"}curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shopping{"host":"shop.example.test","path":"/shopping","cookie":"theme=light"}curl -K hosts.conf -sS -b cookies.txt http://api.example.test:18080/shop/items{"host":"api.example.test","path":"/shop/items","cookie":"lang=ja"}curl -K hosts.conf -sS -b cookies.txt http://notexample.test:18080/shop/items{"host":"notexample.test","path":"/shop/items","cookie":""}curl -K hosts.conf -sS -i -b cookies.txt -c cookies.txt http://shop.example.test:18080/reject
python3 jar.pyHTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 33
Cache-Control: no-store
Set-Cookie: bad=yes; Domain=other.test; Path=/
{"attempted":"unrelated domain"}
theme=light domain=shop.example.test subdomains=FALSE path=/ persistent=False
lang=ja domain=.example.test subdomains=TRUE path=/shop persistent=Truecurl -K hosts.conf -sS -b cookies.txt -c cookies.txt http://shop.example.test:18080/update
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/items{"updated":"theme"}
{"host":"shop.example.test","path":"/shop/items","cookie":"lang=ja; theme=dark"}curl -K hosts.conf -sS -i -b cookies.txt -c cookies.txt http://shop.example.test:18080/delete-wrong
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/itemsHTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 24
Cache-Control: no-store
Set-Cookie: lang=; Domain=example.test; Path=/; Max-Age=0
{"deleted":"lang at /"}
{"host":"shop.example.test","path":"/shop/items","cookie":"lang=ja; theme=dark"}curl -K hosts.conf -sS -i -b cookies.txt -c cookies.txt http://shop.example.test:18080/delete
curl -K hosts.conf -sS -b cookies.txt http://shop.example.test:18080/shop/itemsHTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 28
Cache-Control: no-store
Set-Cookie: lang=; Domain=example.test; Path=/shop; Max-Age=0
{"deleted":"lang at /shop"}
{"host":"shop.example.test","path":"/shop/items","cookie":"theme=dark"}curl -K hosts.conf -sS -j -b cookies.txt http://shop.example.test:18080/shop/items{"host":"shop.example.test","path":"/shop/items","cookie":""}演習完了