Cookie と認証(発展)
HTTP ヘッダ
HTTP におけるリクエストとレスポンスには、ヘッダと呼ばれる Key-Value 型のデータ構造が毎回付加されています。Chrome の開発者ツールでの Network
タブで確認できるので、確認してみましょう。
Cookie
レスポンスヘッダに set-cookie
ヘッダを含めることにより、次回以降のリクエストで、クライアントはそのデータをリクエストヘッダの cookie
ヘッダに入れて毎回送信します。この性質を利用することで、HTTP サーバーはクライアント毎に異なるサービスを提供できるようになります。
Cookie 自体も Key-Value のデータ構造となっているので、set-cookie
ヘッダを複数回送信することにより、複数の cookie を 1 つのレスポンスで送信することができます。例として、Yahoo! Japan のウェブサイト にアクセスした際に、Yahoo! Japan が送信する Cookie の中身を覗いてみましょう。
このレスポンスヘッダを受けて、ブラウザは次のような Cookie を保存します。
ブラウザを更新することで、設定された Cookie が確かにリクエストヘッダの中に含まれて送信されていることがわかります。
Express で Cookie を利用する
Express を用いてレスポンスヘッダに Cookie を付加するには、express.Response#cookie
メソッドを利用します。また、クライアントからのリクエストの cookie
ヘッダを解析するためには、cookie-parser パッケージを利用します。
npm install cookie-parser
を実行して、パッケージをインストールしましょう。Web サーバーのプログラムは次のようになります。
import express from "express";
import cookieParser from "cookie-parser";
const app = express();
app.use(cookieParser());
app.get("/", (request, response) => {
// Cookie の値は文字列なので数値に変換が必要
const count = parseInt(request.cookies.count) || 0;
const newCount = count + 1;
// 変更後の値をレスポンスヘッダに乗せる
response.cookie("count", newCount.toString());
response.send(`${newCount}回目のアクセスですね。`);
});
app.listen(3000);
express.Request#cookies
プロパティ には、ブラウザから送信されていた Cookie がオブジェクト形式で保存されています。ブラウザで表示させると、更新ボタンが押されるたびに数値が増えていることがわかります。
プログラムの流れを整理すると、次の図のようになります。
演習
- Chrome の開発者ツールを用いて、リクエストヘッダとレスポンスヘッダの内容を確認してみましょう。
- シークレットモードでページを開くと値はどうなるでしょうか。
Cookie を用いた認証
ユーザー名とパスワードを用いて認証するタイプのアプリケーションを考えてみましょう。ユーザー名とパスワードを、そのまま Cookie に入れてしまうと、データが悪意のある第三者に奪われてしまうリスクが高まります。
このため、ログインが成功したタイミングで、クライアントに対してランダムな ID を発行し、Cookie に保存させておくことが一般的です(セッション ID と呼ばれる)。次回以降のアクセスでは、このセッション ID を用いて認証を行います。このフローを図にすると、次のようになります。
演習
ユーザーが自分のユーザー名とパスワードでログインし、プロフィールを表示できるウェブアプリケーションを作成してみましょう。
schema.prisma
は次の通りとします。
model User {
id Int @id @default(autoincrement())
username String @unique
password String
}
model Session {
id String @id // 一意でランダムなID
userId Int // User の ID
}