ogatasoが何か書きます

SWE(1年目)が勉強したことを書くヨ

Cookieについて整理する

最近、Go言語で個人開発をやっていてCookieでつまづいたことで、Cookieに対する理解度の低さを改めて感じたので少し調べていきます。

執筆前の僕のCookieの認識は「ブラウザで保存されるデータで、http通信で送信されてログインとかに利用されるやつ」なので、間違っていたら教えてください。

定義

Cloudflareの定義によると「Cookieとは、Webサーバーが生成してWebブラウザーに送信する小さな情報ファイルです。Webブラウザは、受け取ったCookieを所定の期間、またはWebサイト上にユーザーのセッションがある間保存します。また、ユーザーは次回以降Webサーバーにリクエストする際に、関連するCookieを添付します。」とのことです。なので、最初の認識で大体あっている。

https://www.cloudflare.com/ja-jp/learning/privacy/what-are-cookies/#:~:text=Cookie%E3%81%A8%E3%81%AF%E3%80%81Web%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC,Cookie%E3%82%92%E6%B7%BB%E4%BB%98%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

Cookieを保存する流れ

サーバーが発行したJWTなどをCookieに保存する場合、サーバーはHTTPリクエストのヘッダに"Set-Cookie"というフィールドを含み、その中でkey=value;の形で保存して欲しいCookieを指定することができる。また、「;」の後には属性が続いていく。複数のCookieを設定する場合、それぞれのCookieに対して別々のSet-Cookieフィールドが含まれる。つまり、3種類のキーバリューを保存して欲しい場合はSet-Cookieフィールドを3つ指定する。

ちなみにGo言語で設定するならhttpライブラリを使ってこんな感じになる。

http.SetCookie(w, &http.Cookie{
    Name:     "jwt",
    Value:    tokenString,
    Secure:   true,
    HttpOnly: true,
    Path:     "/",
    Expires:  time.Now().Add(60 * 60 * 24 * time.Minute),
    SameSite: http.SameSiteNoneMode,
})

一方で、クライアントがサーバーにリクエストを送る際には"Cookie"というフィールドにキーバリューを詰めて送る。ここで、キーバリューは「;」で分けられる。

属性

この属性がよくわからなかったので調べていく。属性次第ではSet-Cookieを指定してもWebブラウザに保存されなかったり。軽く紹介するだけなので、以下を見た方が多分良い。

developer.mozilla.org

Secure

HTTPSでのみ利用できるようにする。今時基本的にHTTPSなので指定しておいて損はない気がする。ローカルホストだと動かなくなるので注意。 (追記: ブラウザによってはlocalhostでのSecure属性は無視してくれるらしい。やってみるとchromeはそうっぽい。) teratail.com

HttpOnly

この属性が指定されたクッキーはJavaScriptから読まれない。XSS攻撃の対策になる。JSで利用しないならtrueにしておいてよさそう。

Domain

Cookieを受信できるホストを指定する。指定しない場合はサーバと同じドメインをホストとし、サブドメインは除外される。指定した場合はサブドメインも含まれる。例えば、Domain=mozilla.org を設定すると、developer.mozilla.org のようなサブドメインも含まれる。

Path

この属性が指定されると、Pathに一致するページでのみリクエストにクッキーが含まれる。 "/"であれば全てのパスに一致するし、"/users"としたら"/message"には一致せず、クッキーは送信されない。

SameSite

SameSite属性では異なるサイト間でのリクエストでCookieを送るべきかそうでないかを指定できる。これは、CSRFに対しての防御となる。SameSiteの設定にはStrict, Lax, Noneの3種類がある。デフォルトはLax。

Strict ... 元サイトからのリクエストに対してのみCookieを送る。外部サイトからのリダイレクトを含む、他のサイトからのリクエストではCookieは送信されない。

Lax ... 元サイトに対してのみCookieを送るが、外部サイトからリンクを辿った場合にもCookieを送る

None ... 異なるサイト間でも送信できる(ただし、Secure属性を設定する必要がある。)

Expires および MaxAge

Cookieを残す期間を指定することができる。両方指定した場合はMaxAgeが優先される。ちなみに無期限にすることはできないらしい。