セッションとはステートレスなHTTP通信においてステートフルを実現するための情報、Cookieとはブラウザに用意されたデータの保存領域のことをいいます。
セッションの保存先にはいくつか候補がありますが、例えばセッションをCookieに保存することでステートフルなHTTP通信が実現できます。
今回はRailsアプリケーションでセッションとCookieを操作する方法について紹介します。なお、Railsアプリケーションはモノリス、つまりAPIモードで作成していない前提となっています。
目次
基礎知識について
ステートレスとステートフルについて
ステートレスは現在の状態を保持しない、ステートフルは現在の状態を保持することをいいます。
ステートレスのイメージは以下の通りです。ステートレスでは状態が保持されないため、やり取りをするたびに逐一情報を確認する必要があります。
ステートフルのイメージは以下の通りです。ステートフルでは状態が保持されるため、過去の情報をもとにしたやり取りが可能です。
RailsによるCookieの操作方法
Cookieの作成方法
今回は以下のCookieの作成方法について紹介します。
- セッションCookie(Session cookies)
- 持続的Cookie(Permanent cookies)
- 署名付きCookie(Signed cookies)
- 暗号化Cookie(Encrypted cookies)
セッションCookie(Session cookies)の作成方法
セッションCookie(Session cookies)とはセッションと一緒に削除されるCookieです。ブラウザを終了するとセッションCookieは削除されますが、ブラウザによっては再起動時にセッションCookieが復元されるものもあります。1
セッションCookieは一時Cookieと呼ばれることもあります。2
RailsアプリケーションでCookieを操作する場合はAction Controllerのcookies
メソッドを利用します。3
セッションCookieはcoookie[キー名] = 値
で作成します。
例えば以下のようなControllerにアクセスするとSet-Cookie: user_id=1; path=/
がヘッダにセットされたレスポンスが返ってきます。
def index
cookie[:user_id] = 1
end
ブラウザのCookieを確認すると先ほど定義したキーと値がセットされていることがわかります。
持続的Cookie(Permanent cookies)の作成方法
持続的Cookie(Permanent cookies)とはExpires属性の時刻、もしくはMax-Ageの期間が経過した後に削除されるCookieです。1
持続的Cookieは持続Cookie、永続的Cookie、永続Cookie、Persistent cookiesなどと呼ばれることもあります。4 5 2
持続的Cookieはcookies.permanent[キー名] = 値
で作成します。
例えば以下のようなControllerにアクセスするとSet-Cookie: user_id=1; path=/; expires=Fri, 31 Jan 2042 12:56:41 GMT
がヘッダにセットされたレスポンスが返ってきます。
def index
cookies.permanent[:user_id] = 1
end
ブラウザのCookieを確認すると先ほど定義したキーと値がセットされていることがわかります。
署名付きCookie(Signed cookies)の作成方法
署名付きCookieとはsecrets.secret_key_base
によって暗号化されたCookieのことをいいます。第三者は署名付きCookieを改ざんできません。3
署名付きCookieはcookies.signed[キー名] = 値
で作成します。
例えば以下のようなControllerにアクセスするとSet-Cookie: user_id=暗号化された値; path=/
がヘッダにセットされたレスポンスが返ってきます。
def index
cookies.signed[:user_id] = 1
end
ブラウザのCookieを確認すると先ほど定義したキーと暗号化された値がセットされていることがわかります。
暗号化Cookie(Encrypted cookies)の作成方法
暗号化Cookieとはsecrets.secret_key_base
によって暗号化されたCookieのことをいいます。第三者は暗号化Cookieの改ざんだけでなく読み込みもできません。3
暗号化Cookieはcookies.encrypted[キー名] = 値
で作成します。
例えば以下のようなControllerにアクセスするとSet-Cookie: user_id=暗号化された値; path=/
がヘッダにセットされたレスポンスが返ってきます。
def index
cookies.encrypted[:user_id] = 1
end
ブラウザのCookieを確認すると先ほど定義したキーと暗号化された値がセットされていることがわかります。
オプション付きでCookieを作成する方法
Cookieはハッシュ形式でも作成できます。ハッシュ形式を利用したCookieの作成ではオプションが設定できます。
Cookie作成時のオプションは以下の通りです。6
オプション | 説明 | デフォルト |
---|---|---|
:value | 値 | |
:path | 有効なパス | 現在のホスト |
:domain | 有効なドメイン | 現在のホスト |
:expires | 有効期限 | / |
:secure | 暗号化通信でのみCookieを送信 | false |
:httponly | HTTPCookieを有効 | false |
Domain属性とはCookieを受信できるホストを指定するオプションです。
Secure属性とはHTTPS通信の時のみサーバへCookieの送信を許可するオプションです。
HttpOnly属性とはJavaScriptによるCookie操作をできなくするオプションです。
例えば以下のようなControllerにアクセスするとSet-Cookie: user_id=1; path=/; expires=Thu, 10 Feb 2022 00:00:00 GMT
がヘッダにセットされたレスポンスが返ってきます。
def index
cookies[:user_id] = {
value: 1,
expires: "2022-02-10".to_date
}
end
Cookieの取得方法
coookie[キー名]
でCookieの値を取得できます。
例えば、user_id
という値が1
のCookieを取得する方法は以下の通りです。
2: def index
=> 3: binding.pry
4: end
> cookies[:user_id]
=> "1"
署名付きCookieの場合はcoookie[キー名]
で暗号化された値、cookies.signed[キー名]
で復号された値が取得できます。具体例は以下の通りです。
2: def index
=> 3: binding.pry
4: end
# cookies[キー名]で取得すると暗号化された値がそのまま取得される
> cookies[:user_id]
=> "eyJfcmFpbHMiOn..."
# cookies.signed[キー名]で取得すると復号された値が取得できる
> cookies.signed[:user_id]
=> 1
暗号化Cookieの場合はcoookie[キー名]
で暗号化された値、cookies.encrypted[キー名]
で復号された値が取得できます。具体例は以下の通りです。
2: def index
=> 3: binding.pry
4: end
# cookies[キー名]で取得すると暗号化された値がそのまま取得される
> cookies[:user_id]
=> "genL3QVB..."
# cookies.encrypted[キー名]で取得すると復号された値が取得できる
> cookies.encrypted[:user_id]
=> 1
Cookieの削除方法
Cookieはcookies.delete キー名
で削除します。
例えば、user_id
という値が1
のCookieを削除する方法は以下の通りです。
def index
cookies.delete(:user_id)
end
Railsによるセッションの操作方法
セッションの取得方法
セッションの情報はActionDispatch::Request::Sessionクラスのsession
というオブジェクトに保存されています。7
セッション内ではキーによって情報が管理されています。キーの一覧はsession.keys
で、値の一覧はsession.values
で、該当するキーの値はsession[キー名]
で取得します。
From: /app/app/controllers/home_controller.rb:3 HomeController#index:
2: def index
=> 3: binding.pry
> session.keys
=> ["session_id", "_csrf_token"]
> session.values
=> ["0d01dbf0e2e3913395d2daffd31c2a0d", "IUZ2mUVfDWopqh3+SKnE9wmyv2iubqh4QHAIqwtWUEk="]
> session[:session_id]
=> "0d01dbf0e2e3913395d2daffd31c2a0d"
参考: Railsアプリケーションのセッションの保存先について
session
オブジェクトで管理されているRailsアプリケーションのセッションはデフォルトでCookieに保存されます。キー名は_アプリケーション名_session
です。ここでいうアプリケーション名
とはconfig/application.rb
のmodule名を指します。Cookieに保存されるRailsアプリケーションのセッションは暗号化された状態になっています。
なお、Railsのセッションの保存先をCookieからRedisに変更した場合は当該CookieにはセッションIDのみが保存されます。
2: def index
=> 3: binding.pry
4: end
[1] pry(#<HomeController>)> session[:session_id]
=> "fe1c7de48765b8014c8be95a0fd9239f"
Railsアプリケーションのセッションの保存先の変更方法の詳細解説はRailsのセッション保存場所をCookieからRedisに変更する方法で紹介しています。
セッションの作成方法
session[キー名] = 値
でセッションを作成します。
From: /app/app/controllers/home_controller.rb:3 HomeController#index:
2: def index
=> 3: binding.pry
### セッション作成前
> session.keys
=> ["session_id", "_csrf_token"]
> session.values
=> ["be4c69c62729186d9fd61777aab12b4e", "mHVWDCRzUjYjHCAIZ8JEvx+/vb1nfDb0RUkeumJ7Pgs="]
### セッション作成
> session[:user_id] = 1
### セッション作成後
> session.keys
=> ["session_id", "_csrf_token", "user_id"]
> session.values
=> ["be4c69c62729186d9fd61777aab12b4e", "mHVWDCRzUjYjHCAIZ8JEvx+/vb1nfDb0RUkeumJ7Pgs=", 1]
> session[:user_id]
=> 1
セッションの削除方法
session[キー名] = nil
でセッションを削除します。
From: /app/app/controllers/home_controller.rb:3 HomeController#index:
2: def index
=> 3: binding.pry
### セッション削除前
> session.keys
=> ["session_id", "_csrf_token", "user_id"]
> session.values
=> ["be4c69c62729186d9fd61777aab12b4e", "mHVWDCRzUjYjHCAIZ8JEvx+/vb1nfDb0RUkeumJ7Pgs=", 1]
> session[:user_id]
=> 1
### セッション削除
> session[:user_id] = nil
### セッション削除後
> session.keys
=> ["session_id", "_csrf_token", "user_id"]
> session.values
=> ["be4c69c62729186d9fd61777aab12b4e", "mHVWDCRzUjYjHCAIZ8JEvx+/vb1nfDb0RUkeumJ7Pgs=", nil]
> session[:user_id]
=> nil
あるいは、sessionはハッシュオブジェクトであるためsession.delete(キー名)
でも全てのセッションを削除できます。
From: /app/app/controllers/home_controller.rb:3 HomeController#index:
2: def index
=> 3: binding.pry
### セッション削除前
> session.keys
=> ["session_id", "_csrf_token", "user_id"]
> session.values
=> ["02a0411f332a63d221e6554b5984fa92", "KE/RiKhAOS9EQkiv19QbXjK9iG/ZWP5MggT5Jqyk2nc="]
> session[:user_id]
=> 1
### セッション削除
> session.delete(:user_id)
### セッション削除後
> session.keys
=> ["session_id", "_csrf_token"]
> session.values
=> ["02a0411f332a63d221e6554b5984fa92", "KE/RiKhAOS9EQkiv19QbXjK9iG/ZWP5MggT5Jqyk2nc="]
> session[:user_id]
=> nil
セッションのリセット方法
reset_session
で全てのセッション情報を削除します。
From: /app/app/controllers/home_controller.rb:3 HomeController#index:
2: def index
=> 3: binding.pry
### リセット前
> session.keys
=> ["session_id", "_csrf_token"]
> session.values
=> ["cf1307191e2dd9f713b57da47ba7e086", "qvWHoFgFX8NA0fsB/0Ha/Of+4d3xu2kVg3rvlaffS1s="]
### リセット
> reset_session
### リセット後
> session.keys
=> ["session_id"]
> session.values
=> ["6fd19009348e89543e7f76fdee60287f"]
あるいは、sessionはハッシュオブジェクトであるためsession.clear
でも全てのセッションを削除できます。
From: /app/app/controllers/home_controller.rb:3 HomeController#index:
2: def index
=> 3: binding.pry
### リセット前
> session.keys
=> ["session_id", "_csrf_token"]
> session.values
=> ["cf1307191e2dd9f713b57da47ba7e086", "qvWHoFgFX8NA0fsB/0Ha/Of+4d3xu2kVg3rvlaffS1s="]
### リセット
> session.clear
### リセット後
> session.keys
=> []
> session.values
=> []
さいごに
Twitter(@nishina555)やってます。フォローしてもらえるとうれしいです!
RailsによるセッションとCookieの操作方法について書きました。
セッションはステートレスなHTTP通信でステートフルを実現するための情報、Cookieはブラウザに用意されたデータの保存領域です。
セッションをCookieに保存することでステートフルなHTTP通信が実現できます。https://t.co/xDUfEzYudW— 仁科俊晴@エンジニア (@nishina555) January 31, 2022