LINEで現役エンジニアに直接質問してみよう!登録無料

rails6で複数のサブドメインを跨いでCookie&セッションを共有する方法

アキ

独学でプログラミングを勉強しながらWeb制作会社で働き、プログラミングのエンジニア講師も勤めた経験がある、アキです。

  • rails6で複数ドメインを跨いでcookie&セッションを共有する方法を知りたい!
  • rails6でcookie&セッションが正常に共有されているかを確認したい
  • rails6でセッションがどうやって共有されているのか知りたい
  • rails6でセッションが消えてしまう問題の解決方法

結論から言うと、サブドメインを跨いでcookie&セッションを跨いで共有する方法はステップは下記です。

  1. cookieの仕組みを理解する
  2. セッションを保存するcookie名をきめる
  3. セッションをどの範囲のサブドメインで共有するのかを決める
  4. config/application.rbでセッション共有の設定をする

セッションはcookieの仕組みを使って、ユーザーそれぞれ固有の情報を取り扱います。

Railsアプリケーション側から見ると、cookieもsessionもユーザー側に同じように情報を保存します。どのように違うのかも、この記事で解説していきます。

session共有までの基礎知識

http(s)は状態を持たないプロトコル

http(s)はブラウザで情報を通信するときの一般的なプロトコルですが、このプロトコルでは状態(ステート)情報はもっていません。

状態(ステート)情報とは、どんなユーザーがアクセスしたか?今どんなページを見ているのか?などの情報です。

そのような情報は、http(s)ではなく、cookieという機能を使って実現されています。

cookieはHTTPヘッダの一部のSet-Cookieヘッダを含めることで、ブラウザ側に情報を保存することが出来る仕組みで、唯一サーバー側でブラウザに保存する情報を直接指定することができます。

Set-Cookie: name=value
MEMO

Cookieをブラウザに保存する一番簡単な方法は、HTTPヘッダのSet-Cookieヘッダを使うことです。HTTPヘッダを使う他に、javascriptから操作することもできます。

しかし、cookieにはhttponlyという属性があって、javascriptから確認&変更をできなくする事もできるので、全てjavascriptで操作できるわけではありません。

Cookieに付ける属性で、ブラウザに保存するCookeの保存期間や送信ドメイン・パス範囲を指定することができます。

Cookie属性には、下記のようなものがあります。

  • domain 属性
  • path 属性
  • max-age 属性 と expire 属性
  • secure 属性

詳しくは、下記のサイトで詳しく解説されています。

参考 Cookie の仕様とセキュリティyunabe.jp

sessionとは?

sessionとは、cookieでブラウザに情報が保存出来る仕組みをりようして、ユーザー情報などの機密を安全に取り扱えるようにした仕組みのことです。

cookieに保存される情報は、一般的に「セッションID」のみです。サーバー側にセッションIDを送信することで、ユーザー固有のデータを取り出してユーザーを認証することができます。

そのため、セッションIDは「パスワード」や「token」と同じように、機密情報として扱われるべきものです。

セッションの管理方法には、主に使われているものが3つあります。

  • cookie store
  • redis store
  • active record store

railsのsession管理のデフォルトとして使われている仕組みです。セッションIDと共に、それに紐付けられている情報も全て一緒に暗号化されてcookieに保存されます。

セッション管理のためのデータベースは使われません。

redis store

セッション管理にクッキーだけでなくredisと呼ばれるkey-value型データベースを使って管理する仕組みのです。

ブラウザにはCookieを使いセッションIDが保存されます。そして、すべてのリクエスト時においてセッションIDも送信されます。 セッションIDを元にredisで検索し、ユーザー固有の情報を引き出します。この引き出されたユーザー固有の情報がセッション情報です

active record store

Activerecord Storeでは、redisの代わりにActiverecordが使用されます。activerecord使われているデータベースは大体MySQLなので、セッション情報は全て MySQL上で管理されます。

Railsでは、cookieのデータに署名や暗号化を施して保存する仕組みがあり、sessionと同じような使い心地で使う事ができますが、本来全く異なるものです。

cookieは、ブラウザにどのようなデータを保存するのか直接指定することができます。そして、その内容を「署名」「暗号化」を施してデータを保存出来る機能がついているというイメージです。

一方で、セッションはcookieを使い「セッションID」という、ランダムな文字列が保存されています。それをidとしてサーバー側で検索または解析してデータを取り出します。セッションIDは、パスワードやtokenのようなもので、絶対に外部に漏れてはいけません。

そのため、セッション情報は必ずサーバー側からでしかわからないように設計されています。

rails6でセッションを共有する方法

rails6でセッションを共有するには、config/application.rbconfig.session_storeについての設定を追記しなくてはいけません。

追記する内容の概要は下記です。

  • session管理は cookie store で行う
  • railsのアプリケーション名は ExampleApp とする
  • session共有するドメインは example.com とする

という条件だと、下記のように記述します。

config.session_store :cookie_store,
    key: '_example_app_session',
    domain: 'example.com'

rails6でセッションがどうやって共有されている?

railsでは、_example_app_sessionを言う名前のcookieにセッション情報が記録されています。このセッション情報には、セッションの仕組みに重要な「session ID」の他に、「request_from」「_csrf_token」も保存されています。

cookieには、このように保存されています。

  • _example_app_session => mx4w7y4JPOCOkr6fJzSY5S2b+jTwcMSTYSEgE0Ws4qx2m6TGQ8KUleZF2JlhnrlBxO6OBzHJxZspu6m/JI2qehuD/KOBx8BH/+U1uooipvuUxSaXQBlFNGCgqlMVurGuKPRD5y97HURpPK/gTjFS8pVDBNF2wPry9AE7G0wjiqjvyUE6dE9wxUel83R/LV5KB81eGh6j3YNCVwxej9yXB8R6zdtU46RbtutQTE9Ue3j7OW4e3tdu2QBHA8C8UK6sGuWsq7PpqLhi0KzDiZyTUVlInNRHlc4DrvRp7lJiTdBB0N9NCc0BW43cBGCjLHUULq/O4F1p9MiEefUU0xn6xSjPV4RqyfkRut6Y6gM92zk1IVVUexChiLey2TVxqfQYWeftXT9173DzSVV9jrk7–aFMd5q+JL0Hv+tWX–Te2Z/4DcxGEdiiM2NrvvyQ==

base64でエンコードされていますが、これをデコードすることバイナリデータになります。なぜなら、このデータはrailsのsecret_key_baseを使って暗号化されているからです。

なお、復号化すると、中身のデータはこのようになります。

  • session_id => a23a9675793327557551348f246f4f90
  • request_from => https://example.com/cookies
  • _csrf_token => XCMN8/XfiLOWPGGi/5kqBMK8cDRvI/BavE5ipML0Igc=

rails6でセッションが消えてしまう問題の解決方法

セッションが消えてしまう原因には、下記のようなものがあります。

  • csrf_token が不一致しているから
  • secret_key_baseが違うから
  • cookieの設定が間違っているから

csrf_token が不一致しているから

railsでは、csrf tokenが異なると、セッションを初期化してしまうようです。この場合、railsでエラーが表示される時としない時があります。

表示されるときは、GET以外のメソッドでリクエストされた時。表示されないときは、GETでリクエストされた時です。

csrf_tokenはcontrollerで設定されているので、よく確認しましょう

secret_key_baseが違うから

Rails6では、development環境だと自動的にsecret_key_baseが生成され設定されます。

credentials.yml.encsecret_key_baseはproduction時にしか使われないので注意が必要です。

参考 Rails - secret_key_basegithub.com

そのため、サーバーを複数使って開発環境を整えていると、secret_key_baseが異なるためセッションを共有することができません。

secret_key_baseを同じにすれば、正常に動作するようになります。同じにするには、config/secrets.ymlを作成して、下記のようにファイルを編集しましょう。


development:
    secret_key_base: 836fa3665997a860728bcb9e9a1e704d427cfc920e79d847d79c8a9a907b9e965defa4154b2b86bdec6930adbe33f21364523a6f6ce363865724549fdfc08553

そうれば、セッションが共有出来るようになります。

この記事を書いた人

自身がプログラミングを独学で勉強し始めて躓いた経験を元に、これから勉強をする人に向けに「イラスト多めでわかりやすい記事」にこだわって情報を発信しています。

現在はフルスタックエンジニアとしてサービス開発などのお仕事をしています。