テクノロジー

2018年12月28日

ログイン情報保持について学ぼう

ログイン情報はどのように保存されている?

今回は、ログイン情報などを保存する際に大切になる ステートレスな通信、ステートフルな通信 という概念について解説をします。

最近のアプリケーションでは必須である機能の仕組みを学びますので、ぜひご参考にして見てください。

ステートレスの概念とは

HTTP通信は ステートレス な通信です。

これは 前の通信を引き継がない、1つの通信が独立している という意味です。

ステートレスの概念を理解するために、 マクドナルドでポテトを注文する ケースを想定してみましょう。

https://diveintocode.gyazo.com/1059a5f526dd6faed3eaf0713c814c1c

なぜ途中で会話が成立しなくなるのでしょうか?

ステーテレスでは 前の通信(会話)を引き継ぎを行いません。

そのため店員は、 Mサイズで という注文をした時点では、先ほどの ポテトくださいという情報を失っているのです。

https://diveintocode.gyazo.com/4a8277c896d2c5fa25ea2a645da354ab

ステートレス通信は前の通信状態は引き継がないため、誰がどのような状態かを保持しない 仕組みであると言えます。

ステートフルの概念とは

上記の会話が成立するためにはどうすれば良いでしょうか?

答えは簡単で、 前の通信(会話)を引き継げば良い のです。

以下のように客が「ポテトください」と注文した時点で、店員が ポテトが注文されたことを認識 します。

そうすることで客が「Mサイズ」と注文した時に店員がなんのことだか認識することができるのです。

https://diveintocode.gyazo.com/af4a2cfe29dd512bb76d5f3cfcadfe58

当たり前のような注文の流れですが、このように前の通信を引き継ぐことで 誰がどのような状態かを保持する ことができます。

このような通信のことを ステートフル と言います。

HTTP通信の仕組み

では上記の例えを実際のHTTP通信に置き換えてみましょう。

HTTP通信は基本 ステートレス な通信ですが、場合によっては ステートフル にしないと困る時があります。

例えば以下のように DBには保存しないが、ページを超えて保持しておきたい値 が存在する場合です。

  • ネット通販のカートの中身
  • ログインしているユーザ情報

ステートフルな通信を実現するために セッション管理 という仕組みがあります。

まずは以下をご覧下さい。

セッション管理には様々な方法がありますが、ここでは2つ紹介します。

①リクエストに含まれるuser_idを頼りにする

初めてアクセスするユーザがリクエストを出します。

https://diveintocode.gyazo.com/c6802d08d94734e22b13f14f30ba0a1b

コンピュータ側がアクセスしたユーザを初めてであると認識します。

https://diveintocode.gyazo.com/15976cf24b48641f7aa80ef43751e410

コンピュータ側にアクセスしたユーザを覚えるための領域が作成されます。

この領域は セッション領域 と呼ぶことにします。

セッション領域は user_id という番号で管理されます。

セッション領域で管理する値は セッション情報 と呼ばれます。

https://diveintocode.gyazo.com/c7232a101935ebdcdfbbac88584054b4

レスポンスと一緒に user_id が送られ、ブラウザ側の クッキー というテキストファイルで保持されます。

https://diveintocode.gyazo.com/536a9bde03477f1c837afec15fac4649

https://diveintocode.gyazo.com/07b5e40b90c365288252f05674925ee0

2回目以降アクセスする時は アクセスしたユーザコンピュータ側ブラウザ側 の双方が認識している状態になっています。
リクエストと一緒に user_id の情報が乗ったクッキーと、コンピュータ側で保持したい値がコンピュータへ送られます。

https://diveintocode.gyazo.com/57b72f435c787ecc98726b7136440080

送られたuser_idとコンピュータ側のセッション領域に書いてある user_id を比較して、セッション情報が適切なセッション領域に送られます。

https://diveintocode.gyazo.com/b9d707f4668bcd5f99324ef772eb35a8

その結果、以下のようなステートフルな通信を実現できます。

https://diveintocode.gyazo.com/1e348f216235b1f2692c2655c93a868e

②情報を暗号化してブラウザのクッキーのみで保持する

初めてアクセスするユーザがリクエストを出します。

https://diveintocode.gyazo.com/02a9d2352a65597488355c46bfe4f5d8

コンピュータ側がアクセスしたユーザを初めてであると認識します。

https://diveintocode.gyazo.com/134a70c8929cda18f1f0386d898247c4

初めてのユーザには user_id というキーで、 そのユーザのid を代入します。

次に user_id = 1 というセッション情報を シークレットキー という鍵で暗号化してクッキーを生成します。

シークレットキーとは コンピュータ内で暗号化/復号化するための鍵 です。

https://diveintocode.gyazo.com/89800077209970921cd6fe1fc2b31215

レスポンスと一緒に セッション情報が暗号化されたクッキー が送られ、ブラウザ側で保持されます。

クッキーにセッション情報のうちuser_idのみを持たせる方式が一般的です。

なぜならクッキーは 最大で4KB の情報しか保持することができないからです。

https://diveintocode.gyazo.com/a85ad2995ee8885f949d7c67893be42e

この クッキーにセッション情報を全て持たせる 方式は、Railsのデフォルトの設定となっています。

ブラウザで保持されているクッキーに記載されているセッション情報が暗号化されているのは、

ブラウザの検証ツールで クッキーの情報を書き換えられないようにするため です。

もし暗号化しないと、ログインしているユーザのidを書き換えられて、ログインしているユーザが誰だか分からなくなってしまうからです。

さて現状は アクセスしたユーザブラウザ側 のみが認識している状態になっています。

https://diveintocode.gyazo.com/e0840d57bbdd3c5e63aeb9de1cc2400a

2回目以降アクセスする時は、リクエストと一緒に user_id の情報が乗ったクッキーと、コンピュータ側で保持したい値がコンピュータへ送られます。

https://diveintocode.gyazo.com/b8cc9a2456d61dfafeb108150b354a8e

送られたクッキーを復号化して セッション情報 が存在していれば、ユーザを特定することができます。

https://diveintocode.gyazo.com/deb3cf8e325ef9a6090ea097018704b6

認識したところで、セッション情報を追記して新たにクッキーを生成します。

https://diveintocode.gyazo.com/b046c9bd0e82884c776959564968c7fc

最後に再び暗号化して、新しいセッション情報を元にして作られたクッキーがレスポンスとして一緒に送られます。

https://diveintocode.gyazo.com/4ea729ac290a793652d58dc5c070c5f1

https://diveintocode.gyazo.com/260d754fd204aa30cfbd4270850726e5

その結果以下のようにブラウザ側でセッション情報が保持されます。

https://diveintocode.gyazo.com/68ef58b39f6b29ef7f7865a5cdd2ab3e

このやり方をまとめると以下のようになります。

  • クッキーだけに全てのセッション情報を集約する
  • クッキーを乗っ取られると全てが乗っ取られると言っても過言ではない
  • コンピュータ側はセッション情報を何も把握していない
  • セッション情報を暗号化してクッキーを生成するのは、クッキーを乗っ取られないようにするため
  • コンピュータは復号化されたクッキーを見て、ユーザを認識できる能力がある

つまりクッキーが持っているセッション情報を復号化して 誰がどのような状態か を把握しているのです。

最後の コンピュータは復号化されたクッキーを見て、ユーザを認識できる能力がある に関してですが、

これはコンピュータ内部で生成されるロジックに起因し、深い知識が必要となるため、ここでは省略させていただきます。

その他のセッション管理方法

先ほどセッション管理方法を2つ紹介しましたが、セッション管理は他にも方法があります。

  • クッキーにセッション情報を保持させ、リクエストのuser_idを頼りにする
    セッション管理は他にも管理方法があります。
  • クッキーにセッション情報を暗号化してブラウザに保持させる
  • コンピュータ内のメモリにセッション情報を保持させる
  • コンピュータ内のDBにセッション情報を保持させる

ここではすべてを紹介しませんが、セッション管理は様々な方法があることを理解しましょう。

セッション管理まとめ

  

  • 誰がどのような状態かを保持しておきたい時には ステートフル にする必要がある
  • 基本はステートレスなので、ステートフルにするためには セッション管理 をする必要がある
  • セッション管理をするためには クッキーセッション情報 が必要

ここでは4つの重要単語が出てきました。

最後に、これらの単語の意味を復習します。

  • セッション管理:ステートフルにするための仕組み
  • セッション情報:保持したい値
  • クッキー:ブラウザ側でセッション情報を保持するテキストファイル
  • シークレットキー:セッション情報をコンピュータ内で暗号化/復号化するための鍵

いかがでしたでしょうか?

セッション管理の方法は、アプリケーション制作において重要な知識ですので、一つずつ着実に理解していきましょう!

DIVE INTO CODEのことをもっと知ってみませんか?