Railsにおけるsessionについて整理してみた



railsチュートリアルをもりもりとやっております。
第8章にて取り扱われている「session」について、今回は自分の理解のために整理したいと思い記事を書きました。
初心者なため、なにか間違いなどあればコメントにてご指摘いただけると嬉しいです。

<h2>そもそもsessionって何？</h2>
（答え）
"statefullな通信"を実現する"仕組み"のこと。

<h3>ステートフルとはなにか？</h3>
私たちが普段使っているHTMLは、statelessな通信を行っています。
＊state (状態) less（ない）= 1回1回が独立したやりとり

この通信は、ブラウザ⇄サーバ間のやりとりは1往復ごとに独立しており、
以前の情報などは引き継ぐことはできません。

ただ、この話を聞いた時に疑問に思うかもしれません。
HTMLの通信は全て独立したやりとりならば、例えば、ショッピングサイトなどで、
カートに買いたい商品を入れていく際、情報は引き継がれないため、
ページ遷移するとカートは空になってしまうはずです。


なので、**ステートレスなHTMLの通信を"ステートフル"にするのがセッションという仕組みです。**
＊state （状態） full（保持する）＝ユーザ情報などの状態を"保持"したままやりとりを行う

この通信では、ブラウザ⇄サーバ間で通信に情報を付け加えてやりとりをすることで、
このやりとり全体を一連の動作のようにすることが可能です。

上の例でいえば、会員としてログインしたサイトで、会員情報を保持しながら様々なページに飛べたり
ショッピングサイトで、カートの中にどんどんと物を入れていくことができたりと、何かと便利です。

HTMLでの"ステートフルな通信"はセッションという仕組みで成り立っています。

参考：[session通信](https://www.slideshare.net/carotene4035/sessionrailscookie-store)

<h2>sessionはどうやってやりとりされるの？</h2>
（答え）
一般的には、ブラウザ側から送られる"cookie"に含まれるsession IDを
サーバ側で取得・照合し、セッション内容を取り出してやり取りをしている。
ブラウザを閉じることで、セッションは削除される。


<h3>Cookieとはなにか？</h3>
クッキーは一言でいうと、webブラウザ側で保持している情報です。

セッションが必ずしもcookieを扱うとは限りませんが、一般的に用いられるのは確かです。
Railsもcookieを標準としているため、ここではcookieを前提にしてお話します。

〜cookieのざっくりとした流れ〜
----
**①アクセス初回**
ブラウザ側が、サーバ側にアクセス。
サーバ側が、そのブラウザの識別情報（例えばログイン情報など）をHTTPヘッダに含めて送信
その情報をブラウザが保存する（Cookie情報がこれ）

**②それ以降のアクセス**
ブラウザ側が、保存していたcookie情報をHTTPヘッダに含めてサーバ側へ送信。
サーバ側はその情報を元に、アクセスしてきた相手を判断する。




このように、cookieはブラウザ側で保持している情報のことで、その中にsession IDも含めて送ってあげることで、サーバ側で「どんな内容やり取りしてたっけ？」がわかるようになります。
ちなみにsessionの内容自体は、webサーバ側が保持しており、cookieの中にあるsession IDはそれを呼び出すためのIDになります。

セッションはあくまで一時的なものであり、基本的にはブラウザを閉じた段階で消去されます。


<h2>Railsにおけるsessionとは？</h2>
概念の話は以上として、次からはRailsにおけるsessionの内容について整理していきます。
railsではユーザごとにセッションを設定できます。セッションは、コントローラとビューでのみ利用可能。
また、以下のストレージを選ぶことができます。

| ストレージ | 説明 |
|:--|:--|
| ActionDispatch::Session::CookieStore:  | すべてのセッションをクライアント側のブラウザのcookieに保存する  |
| ActionDispatch::Session::CacheStore:  | データをRailsのキャッシュに保存する  |
| ActionDispatch::Session::ActiveRecordStore:  |  Active Recordを用いてデータベースに保存する (activerecord-session_store gemが必要) |
| ActionDispatch::Session::MemCacheStore: |  データをmemcachedクラスタに保存する (この実装は古いのでCacheStoreを検討すべき) |
 

先ほど説明したように、基本的にはsession IDはCookieに保存されサーバに渡されますが、
デフォルトで使用されている`CookieStore`に関しては、**sessionの情報自体をCookie側に保存します。**

CookieStoreは、以下の**メリット**を持っています。
・非常に軽量であることと
・Webアプリでセッションを利用するため一式が準備済み
・cookieデータは改竄防止のために暗号署名が与えられており、さらにcookie自身も暗号化されているので、内容を他人に読まれない (改ざんされたcookieはRails側が拒否)

ただし以下の**デメリット**もあります。
・cookieの上限は4KB
・cookieはクライアント側(ブラウザ)に保存されるので、cookieの期限切れのcookieの内容が残っている可能性もあり
・クライアントのcookieが他のコンピュータにコピーされる可能性もあり
・セッションcookieはひとりでに失効することはないため、悪用目的で使い回される可能性もあり

基本的には、Railsが推奨しているCookieStoreを使うのがいいと思いますが、
状況に応じて使い分けが必要という風に捉えました。

参照：[railsガイド セッション](https://railsguides.jp/action_controller_overview.html#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3)


<h2>sessionの操作</h2>

以下は全てデフォルトで使用されているCookieStoreでの操作です。


**・sessionを作る**

```
session[:user_id] = @user.id
```

sessionメソッドはハッシュ値で設定できます。
設定することによりこのsessionの情報を含んだ暗号化済みのcookieが生成されます。



**・sessionを参照する**

```
user = User.find(id: session[:user_id])
```
sessionの情報は、簡単に参照可能です。
セッションメソッドが呼び出されると内部でcookieの情報が復号され、session[:シンボル]で値を取得することができます。

**・sessionを削除する**

```
#やってることは全部一緒
session[:user_id] = nil
session[:user_id].clear
session.delete(:user_id)
```
nilで書き換えたり、clearやdeleteなどで情報を削除することが可能です。


<h2>終わりに</h2>
私がsessionを学んでいて一番疑問に思ったのは、sessionとcookieの関係性でした。
概念で話されている内容と、Railsのsessionメソッド(CookieStore)の挙動が違うというのが
よく理解できておらず、？がいっぱいに・・・笑

改めて、整理してみると自分が理解できていなかった点が洗い出せてすっきりしました。
引き続きRailsチュートリアル、頑張っていきたいと思います。


<h2>参考にさせていただいたサイト様</h2>
ありがとうございます！
https://ja.wikipedia.org/wiki/HTTP_cookie
https://qiita.com/hththt/items/07136ad74127999df271
https://qiita.com/hot_study_man/items/147f8b767b4135fe6fe4
https://www.justinweiss.com/articles/how-rails-sessions-work/
https://railsguides.jp/security.html