Cookie / Session / Cache

## はじめに

最近，インターン先での開発業務の中で「Cookieとかセッションとかなんとなく使ってるけど人には説明できないな．」と感じ，改めて調べたの内容をまとめました．

各情報源をもとに，自分なりに噛み砕いて理解したつもりですが，もし誤りがあれば，コメントをいただけますと励みになります．

## Cookie

- **ブラウザにテキスト情報を保存する仕組み**
- 通常のHTTP通信は**ステートレス**である．（情報を持たないでリクエストに対してレスポンスを返すだけ，状態を持たない）
- Cookieを保存することで，**ユーザごとの情報**を識別（後述）し，再ログイン時に情報を入力する手間が省ける．（webページにおける利便性の向上，サーバサイドではユーザ情報を管理できる）
- 上記を実現，即ちWebページに状態を持たせるためには，**Cookieによるセッションの管理**が必要


<details><summary>ログイン状態の維持の例</summary>

1. 初回ログイン時にサーバがブラウザにCookieを発行（具体的には、CookieはHTTPヘッダーの一部としてブラウザに送信）し，ブラウザはそれを保存する
2. 次回ログイン時にCookieを識別子としてサーバに送信
3. サーバは2で送られてきた情報を元に個別の情報をと合わせてページを表示する
    
  ![IMG_EAAC12CF7220-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1071957/7d1f495c-db9a-b89c-a773-e1ad28b2b94f.jpeg)
</details>

**memo**

<details><summary>注意点(なりすまし)</summary>

- 識別子が推測できないものにする
- 識別子が漏洩しないこと

</details>

<details><summary>Cookieの有効期限</summary>

- Max-Age属性もExpires属性も指定されていない場合はブラウザを閉じるタイミングでCookieが消滅する

</details>

## Session

- **Cookieを使用した一連の操作のこと**． Cookie によるセッションIDの管理が行われる．
- サーバはクライアントからログイン時にユーザ情報を受け取り，セッションIDを生成，Cookieに載せてクライアントに返すことで，ユーザによる一連の操作（状態）を管理することができる．

> アプリケーションはセッションを用いて、多くのユーザーがアプリケーションとやりとりできるようにしつつ、各ユーザー固有のステートを維持します。たとえばセッションを用いることで、ユーザーが認証されれば以後のリクエストでサインインしたままにできます。
> 
> 
> [Rails セキュリティガイド - Railsガイド](https://railsguides.jp/security.html#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B)
> 

![IMG_D787C65DD7CF-1.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1071957/c5f72d6b-e707-786f-ff44-b20a02d2ad12.jpeg)


**memo**

- 通常、同じユーザーが異なる端末でログインする場合、各端末ごとに異なるセッションが作成され、ユーザーごとに異なるセッション情報が管理される．

    <details><summary>セッション情報の管理方法</summary>

    - ファイルに保存する
    - Cookie内に暗号化して持つ
    - データベースに保存する
    - memcachedなどのKVSに保存する

    </details>

    <details><summary>複数の端末で同じセッションを共有する方法</summary>
    
    - セッションデータの共有：サーバサイドの共有ストレージ（DB，キャッシュ，ファイルシステムなどに保存）
    - セッションIDの共有：特定のセッションIDを異なる端末で共有できるように調整する．これにより，同じセッションにアクセスできる．ただし，セキュリティの配慮が必要であり，慎重に実装する必要がある．
    - クライアント側での同期：WebSocketを使用したリアルタイムなデータ同期など

    </details>

    <details><summary>セッションとDBの使い分け</summary>
    
    > データベースもリクエスト外にデータを保存していますので、データベースを使用してもリクエスト間でデータを共有することができます。
    セッションとデータベースのどちらに保存するかは、そのデータをずっと残したいか(永続化したいか)で決めます。
    > 
    > 
    > 　セッションには有効期限という概念があります。
    > 最終アクセス後、決められた時間が経過すると自動的に削除されます。
    > 一定日数や時間経過後にアクセスするとログイン画面に戻っているようなWebアプリケーションを使った事があると思います。これはセッションの有効期限後に自動削除される仕組みによります。
    > 
    > 　一方データベースには自動的に削除される仕組みはありません。
    > 
    > 　ユーザの名前は消えてしまうと問題になりますが、ログインしたユーザIDはセキュリティの観点から一定期間後には消えてほしいデータです。
    > そのためユーザ名はデータベースに格納し、ログインしたユーザIDはセッションに格納します。
    > 
    > [【Rails】sessionの使い方と仕組みを徹底解説【初心者向け】 | IchigiBlog](https://ichigick.com/rails-session/)
    > 

    </details>

## Cache


> 「キャッシュ（caching）」とは、リクエスト・レスポンスのサイクルの中で生成されたコンテンツを保存しておき、次回同じようなリクエストが発生したときのレスポンスでそのコンテンツを再利用することを指します。
> 
> 
> [Rails のキャッシュ機構 - Railsガイド](https://railsguides.jp/caching_with_rails.html)
> 

<details><summary>Railsにおけるキャッシュ</summary>

詳細:[Rails のキャッシュ機構 - Railsガイド](https://railsguides.jp/caching_with_rails.html)

1. **ページキャッシュ**
    - ページの内容をブラウザが保存し，再表示する際に初回より高速にページを表示する機能
    - 一度キャッシュされたページは、サーバーサイドの処理をスキップしてキャッシュから即座に提供できます。これは静的なページや、あまり頻繁に変更されないページに適している．
    - 認証が必要なページには適用できない
        
    > ページキャッシュ機能は、Rails 4で本体から削除されてgem化されました。[actionpack-page_caching](https://github.com/rails/actionpack-page_caching) gemを参照してください。
    > 
    > 
    > [Rails のキャッシュ機構 - Railsガイド](https://railsguides.jp/caching_with_rails.html)
    > 
    <br>


2. **アクションキャッシュ** 
    - キャッシュを有効にするアクションがリクエストされると，Railsはそのアクションのレスポンスをキャッシュストアに保存し，次回同じリクエストに対して、キャッシュからレスポンスが提供され，コントローラーアクションは実行されず，データベースクエリやビューの生成がスキップされる．
        
    > アクションキャッシュ機能は、Rails 4から削除されました。詳しくは[actionpack-action_caching](https://github.com/rails/actionpack-action_caching) gemを参照してください。推奨される新しい方法については、[DHH's key-based cache expiration overview](https://signalvnoise.com/posts/3113-how-key-based-cache-expiration-works)を参照してください。
    > 
    > 
    > [Rails のキャッシュ機構 - Railsガイド](https://railsguides.jp/caching_with_rails.html)
    > 
    <br>    
3. **フラグメントキャッシュ**
    - ビューの一部（フラグメント）をキャッシュする．ビュー内の特定の部分をキャッシュすることで，リクエストの処理時間を削減し，ページの表示速度を向上させます。フラグメントキャッシュは**`cache`**ヘルパーメソッドを使用して実装できる．
            
        ```ruby
        # ページ内で表示する製品（product）を個別にキャッシュしたい場合
        <% @products.each do |product| %>
          <% cache product do %>
            <%= render product %>
          <% end %>
        <% end %>
        ```

</details>

**memo**

- **Webページの情報**を管理する．
- セッションにより情報を管理される．
- 同じログイン情報で別の端末でログインした場合，通常のキャッシュは新しいセッションに関連付けられる．            
- キャッシュストア…アプリケーションがデータを一時的に保存するためのストレージ
    
    

## まとめ


- **Cookie**　… ブラウザにテキスト情報を保存し，HTTPヘッダーに情報を付与することでクライアント/サーバ間でユーザ情報を管理する．
- **Session**… ユーザによるWebページ上での一連の操作のこと．サーバはクライアントからログイン時にユーザ情報を受け取り，セッションIDを生成，Cookieに載せてクライアントに返すことで，ユーザによる一連の操作（状態）を管理することができる．
- **Cache** … Webページの情報を保存，再利用することでページの表示を高速化する
<br>
違いについては，自分なりに理解できました，この後の実務や趣味開発の中で使い分けや実装方法についても知見を深め，使いこなせるようにしていきたいです．
以上，最後まで読んでいただきありがとうございました．

## 参考文献

- Rails セキュリティガイド - Railsガイド，[https://railsguides.jp/security.html](https://railsguides.jp/security.html)
- Rails のキャッシュ機構 - Railsガイド，[https://railsguides.jp/caching_with_rails.html](https://railsguides.jp/caching_with_rails.html)
- Cookieとキャッシュとセッションの違いをまとめた #HTTP - Qiita，[https://qiita.com/taoki11111/items/4c103683ac46ec851017](https://qiita.com/taoki11111/items/4c103683ac46ec851017)
    
    

※ いずれのページも最終閲覧日は2023/11/07です．