Rails チュートリアル九章

9.1 Remember 機能

ユーザーのウェブサイトを閉じた後でもログイン状態を有効にする機能
チェックボックスをログインフォームに追加する

9.1.1 記憶トークンと暗号化

sessionメソッドはブラウザーを閉じると消えるセッションの永続化として記憶トークンを生成しcookiesメソッドによる永続的や安全性の高い記憶ダイジェストによるトークン認証に記憶トークンを活用(トークンはパスワードと同じ秘密情報。コンピュータの作成・管理する情報)

cookiesメソッド

自動的に安全性は高くならない。セッションハイジャックの攻撃を受けやすくなるセッションハイジャックは記憶トークンを盗みログインすること。

永続セッションを生成

記憶トークンにはランダムな文字列を生成して用いる。
ブラウザのcookiesにトークンを保存するときには、有効期限を設定する。
トークンはハッシュ値に変換してからデータベースに保存する。
ブラウザのcookiesに保存するユーザーIDは暗号化しておく。

データモデルをアプリケーションに追加する
マイグレーションを実行

rails g migration add_remember_digest_to_users remember_digest:string

記憶トークンを決める

SecureRandom.urlsafe_base64

ランダムなトークンを繰り返す

   SecureRandom.urlsafe_base64

ログイン状態の保持

user.rememberメソッドが動作するからユーザーの暗号化済みIDと記憶トークンをブラウザの永続cookiesに保存して永続セッションのじゅんびができた記憶トークンと記憶ダイジェストを比較するauthenticated?メソッド
をUserモデルの中に置く

def authenticated?(remember_token)
   BCrypt::Password.new(remember_digest).is_password?(remember_token)
 end
 

記憶トークンcookieに対応するユーザーを返す

 def current_user
   if (user_id = session[:user_id])
     @current_user ||= User.find_by(id: user_id)
   elsif (user_id = cookies.signed[:user_id])
     user = User.find_by(id: user_id)
     if user && user.authenticated?(cookies[:remember_token])
       log_in user
       @current_user = user
     end
   end
 end

ユーザーを忘れる

user.forgetメソッド

def forget
   update_attribute(:remember_digest, nil)
 end

# 永続的セッションを破棄する

def forget(user)
   user.forget
   cookies.delete(:user_id)
   cookies.delete(:remember_token)
 end

9.1.4 2つの目立たないバグ

ユーザーがログイン中のみログアウトさせる

def current_user
 if (user_id = session[:user_id])
   @current_user ||= User.find_by(id: user_id)
 elsif (user_id = cookies.signed[:user_id])
   user = User.find_by(id: user_id)
   if user && user.authenticated?(cookies[:remember_token])
     log_in user
     @current_user = user
   end
 end
end

user && user.authenticated?(cookies[:remember_token])


9.2 remember チェックぼっくす

チェックボックスでログイン状態にしておく

<%= f.label :remember_me, class: "checkbox inline" do %>
 <%= f.check_box :remember_me %>
 <span>Remember me on this computer</span>
<% end %>

チェックボックスの送信結果を処理する

  params[:session][:remember_me] == '1' ? remember(user) : forget(user)
  



この記事が気に入ったらサポートをしてみませんか?