blog

クッキーの学習 - 最初からあきらめる!

最近、開発プロセスでは、クッキーについてのピットのいくつかに遭遇し、一度クッキーを整理するためにこの機会を利用し、メモリを強化するために、エラーがありますが、また、お兄さんによって修正されることを願っ...

Jan 20, 2020 · 5 min. read
シェア

前に書く

最近、開発プロセスでは、クッキーのピットについてのいくつかに遭遇し、メモリを強化するために、一度クッキーを整理するために、この機会を利用し、間違いがありますが、また修正されるようにお兄さんを願っています。

cookie

  1. クッキーはデータを渡すための技術であり、クッキーを通してフロントエンドからバックエンドにいくつかのデータを渡すことができ、バックエンドのAPIインターフェイスはreq.cookiesプロパティを通して取得することができます。
  2. クッキーとは、ブラウザが状態を管理するために使用するファイルのことで、このファイルの内容をJSコードで読み書きすることで、状態を管理するという目的を達成することができます。

クッキーが何であるかを知りながら、なぜクッキーを使うのでしょうか?httpは状態を保存しないプロトコルだからです。つまり、サーバーがリクエストを処理しているとき、これらのリクエストが同じブラウザから来たものかどうかがはっきりせず、関連するロジックがうまく処理されないからです。

そこで開発者たちは考えました:サーバにリクエストを送信し、何らかの状態値を渡すことができ、これらのリクエストがブラウザから来たことをサーバに知らせることができれば、問題は解決しないのではないか?こうしてクッキーの技術が生まれました。

cookie

クッキーには5つの共通属性があり、ここで簡単に説明します。

  1. name: クッキーの名前。1つのドメイン配下のクッキーの名前を繰り返すことはできません。

  2. value cookie

  3. path: クッキーが保存されるディレクトリ、デフォルト値は / です。クッキーディレクトリはクッキーのアクセス権を管理する機能を持ちます。

    そうすると、/root/配下のすべてのページがcookie1にアクセスでき、/root/keys/, /root/phones/配下のページはcookie2にアクセスできず、/root/book/配下のページだけがcookie2にアクセスできます。

  4. Expires: 後述するクッキーの有効期限。

  5. セキュリティ: クッキーの Secure 属性は、クッキーの通信を暗号化された伝送に限定し、ブラウザにクッキーを安全な/暗号化された 接続上でのみ使用するよう指示することを意味します。ウェブ・サーバが安全でない接続から安全な属性のクッキーを設定しても、クッキーがクライアントに送信されるとき、中間者攻撃によって傍受される可能性があります。

  6. HttpOnly 属性を持つクッキーは、JavaScript を呼び出す(例えば document.cookie を参照する)など、HTTP 以外の手段ではアクセスできません。

    その結果、クロスドメイン・スクリプティングによってそのようなクッキーを盗むことはできません。特に、FacebookとGoogleはHttpOnly属性を広く利用しています。

クッキーの設定方法

フロントエンドでクッキーを設定する方法
// 最も単純なクッキーを設定し、他の属性はデフォルトに設定する。
document.cookie = "hobby=book;"
// クッキーの有効期限を2時間に設定する。
let expiresDate = new Date();
expiresDate.setTime(expiresDate.getTime() + (1000 * 60 * 60 * 2))
document.cookie = `hobby1=book; expires=${expiresDate.toGMTString()}`;
フロントエンドでクッキーを読む方法

例えば、"name=Allen; height=175; gender=male "のように、すべてのクッキー文字列を含むクッキーを document.cookie で直接取得することができます。クッキーは、オブジェクトを返す次のような関数でも扱うことができます:

function getCookieObj() {
 let cookieArray = document.cookie.trim().split(";");
 let equalIndex = 0;
 let cookieObj = {};
 cookieArray.forEach(cookie => {
 if (cookie.trim().split("=").shift()) {
 equalIndex = cookie.trim().indexOf("=");
 cookieObj[cookie.trim().split("=").shift()] = cookie.trim().substring(equalIndex + 1);
 }
 });
 
 return cookieObj;
}
console.log(getCookieObj());
/*
{
 gender: "male",
 height: "175",
 name: "Allen"
}
*/
バックエンドでクッキーを設定する方法

プロジェクトのバックエンドで使用されている言語に関係なく、関連するAPIによって返されるHTTPレスポンスヘッダが以下の情報を含んでいる限り、バックエンドはクッキーを設定することを要求し、フロントエンドはこのレスポンスを受け取った後、このクッキーをブラウザに保存すると仮定されます:

Set-cookie: name=name; expires=date; path=path; domain=domain

Node.jsを例にとると、以下のコードを使ってクッキーを設定することができます:

// 基本的なクッキーを設定する
res.writeHead(200, {
 'Set-Cookie': 'myCookie=test',
 'Content-Type': 'text/plain'
});
// 複数のクッキーを設定する
res.writeHead(200, {
 'Set-Cookie': ["aaa=bbb","ccc=ddd","eee=fff"],
 'Content-Type': 'text/plain'
});
// 複数の属性を持つクッキーを設定する
res.writeHead(200, {
 'Set-Cookie': 'myCookie=test; Expires=Wed, 13-Jan-2021 22:23:01 GMT;HttpOnly ',
 'Content-Type': 'text/html'
});

あなたのプロジェクトでExpress.jsフレームワークを使用している場合は、クッキーを設定する方が簡単です:

// 直接Express.jsクッキーを設定するためのAPIを提供する。
function(req, res, next){
 ...
 res.cookie(name, value [, options]);
 res.cookie('user',1,{ expires: new Date(Date.now() + 100), httpOnly: true });
 ...
}

バックエンドでクッキーを読む方法

リクエストを送信するバックエンドへのフロントエンドは、クッキーは自動的にHTTPリクエストヘッダに配置されますので、バックエンドが直接取得するリクエストにすることができます、以下は例としてNode.jsにまだです:

http.createServer(function (req, res) {
	...
	console.log(req.headers.cookie); // クライアント側のクッキーを取得する
	...
}).listen(8000);

したがって、Express.jsフレームワークを使用すれば、クッキーを取得するのが簡単になります:

var express=require('express');
var cookie=require('cookie-parser'); 
var app=express();
app.use(cookie());	// クッキー・パーサー・ミドルウェアを使う
app.get('/',function(req,res){
	...
 console.log(req.cookies);	// req.cookiesがクッキー・オブジェクトの場合、キーと値のペアを介して直接クッキーを取得することができる。
 ...
});

クッキーの使用に関するあなた自身の経験

私自身の開発経験と合わせて、私自身が学んだことをいくつかご紹介します:

  1. ユーザー情報を記録するjwtなどのクッキーには、機密情報を入れないでください。
  2. フロントエンドでのクッキーの設定を最小限にし、可能であればバックエンドのAPIニーモニック経由で設定し、Secure属性とHttPOnly属性をtrueに設定することで、XSS攻撃を防ぐことができます。
  3. クッキーの中に保存する必要があるデータについては、クッキーの有効期限の設定に注意してください。
Read next