cookie, session, tokenを区別するために前提として理解してほしいことは、
「httpにはステートレス」ということです。
ステートレス
ステートレス、つまり状態を持たないことです。
誰からリクエストが来たのかを覚える必要は一切なく、ただただリクエストに対してレスポンスを返せばいいのです。
しかし、webアプリケーションが進化するようになってから、httpがステートレスの状態だとUserにとってとても困ります。
httpがステートレスのため、ログインしても、自分が過去にいいねした商品、ショッピングカートに入れた商品が見れません。
Sessionによる認証
そこで頭のいい人は、Session idを使ってhttpをステートフルにするための方法を考えました。session idはただの文字列だと思って大丈夫です。Session idはweb serverから生成し、Userに割り当てします。また、違うUserがもらったsession idは違います。 次回からhttp requestが送られる際に、session idも一緒に添付されます。
このsession idを持って、web serverが誰から来たのリクエストを判断することができます!同じsession idのため、過去のリクエストの内容ももちろん確認することができるため、httpはステートフルになりました!
Sessionによる認証のデメリット
しかし、session idは全部web serverから生成し、web serverはみんなのsession idを保存しないといけないため、とても大変です。そうです、実はserverに大きな負担をかけています。 またweb serverの拡張能力を制限しています。
例えば、serverAがツヤさんのリスエクトをリダイレクト処理でserver Bに転送されました。server Bはツヤさんのsession idを持っていません。 これを解決するため、ツヤさんのsession idをserver Aからserver Bにコピーしなければいけません。
もっと楽にsession idを確認する方法はないかなと、session id保存用のserverを構築して、毎回リクエストが来たら、
server Aとserver Bもそこからsession idを確認すればいいじゃんと考えている方もいると思いますが、実はそれもリスキーです。例えば、ある日にsession id保存用のserverがダウンしたら、大変なことになります。 説明からわかったように、sessionによる認証の管理が大変です。
Tokenによる認証
そこで、違う視点から問題を解決する方が現れました。なんでsession idはserverで保存しないといけないの? webブラウザで保存すればいいじゃない。しかし、web serverで保存しないと、どうやってこれかのsession idはweb serverが生成したものだと証明できるのですか? ここからはTokenの出番です。
例えば、ツヤさんがあるショッピングサイトをログインしました。
web serverがTokenを生成し、Tokenの中にツヤさんのUser idが含まれていて、ツヤさんに渡しします。
次回からツヤさんが訪問する際に、Tokenをhttp Headerに入れて、web serverを訪問します。 またTokenを偽造できないように暗号化する必要があります。
例えばHMAC-SHA256のアルゴリズを使って、Tokenのデータを暗号化します。
このTokenについて、 web serverは保存しません。次回、ツヤさんが来た際に、同様なアルゴリズを使って、Tokenのデータを暗号化します。この二つの暗号化の結果を比較します。
こもし同じであれば、ツヤさんが登録済みのことがわかります。直接ツヤさんのUser idを受け取ります。もし違っていれば、データは改ざんされたことが推測できます。
また、Tokenの中のデータは明文保存のため、誰かに見られる可能性はあります。そのために、暗証番号のような秘密情報はTokenに入れてはいけません。
これでweb serverの負担は大幅軽減されました。やることとしては、Tokenを生成し、Tokenの認証だけです。sessionを保存するためのスペースが空きました。
Cookie
webブラウザが永久に保存できるデータのことです。 Cookieはweb serverが生成し、webブラウザに送ります。ブラウザがCookieをstorageに保存します。次回同じサイトをアクセスする際に、そのCookieをweb serverに送ります。一般的にCookieのサイズは小さいです。
Session
例えば、誰かと会話する際に、今会話している対象が誰なのかを判明するため、Sessionを使います。Sessionの情報はweb serverに保存されます。web serverがsessionの情報を臨時にweb serverに保存します。Userがブラウザを閉じたら、web serverに保存されたsession idが自動に削除されます。そのため、ブラウザが閉じられた後のアクセスについて、web serverがまた新しいsession idを生成してブラウザに渡します。
Sessionによる認証のデメリットとしては、リクエストがあるたびに、web serverでSessionの参照と保存を行います。 そのため、処理が遅くなるのが考えられます。
最後に
基本的に大規模の開発ではToken認証が主流です。Token認証については、サーバ側で情報を管理しませんので、ステートレスとなります。並列処理も実施しやすくなります。大規模の開発ではToken認証の方が適しています。 また、ネイティブアプリの開発にCookieの保存ができないので、Tokenは向いています。 Token認証の方が安全性が高いです。特にCSRFを防ぐために有効です。
CSRFについて話すと、長くなりますので、次回に書きたいと思います。
Tokenを使うことによって、Sessionに対する操作が減り、Tokenには時効もあるため、安全性が向上されます。
Token認証のデメリットとしては、TokenのデータサイズはSessionより大きいです。ブラウザでTokenを管理する場所として、LocalStorageかCookieに保存できます。また、Cookieは保存上限が4KBのため、保存する際に注意が必要です。