【86日目】【1日20分のRailsチュートリアル】【第8章】ログイン状態の保持機能を追加する
今日は「8.4.2 ログイン状態の保持」のトークンが記憶ダイジェストと一致するか確認するから。
8.4.2 ログイン状態の保持
攻撃者が仮に両方のcookiesを奪い取ることに成功したとしても、本物のユーザーがログアウトするとログインできないようになっています。
記憶トークンとユーザーIDのcookiesを奪い取られてもログインできないらしい。
渡されたトークンがユーザーの記憶ダイジェストと一致することを確認します。
secure_passwordのソースコードを参考にして最終的には下記のような形に。
is_password?
がどういうメソッドなのかよく分からないなぁ…。
BCrypt::Password.new(remember_digest).is_password?(remember_token)
上記を踏まえUserモデルにトークンをチェックするメソッドを追加。
app/models/user.rb
# 渡されたトークンがダイジェストと一致したらtrueを返す def authenticated?(remember_token) BCrypt::Password.new(remember_digest).is_password?(remember_token) end
ログインするときの処理にremember
メソッドを追加。
app/controllers/sessions_controller.rb
: if user && user.authenticate(params[:session][:password]) log_in user remember user redirect_to user else :
Sessionヘルパーにremember
メソッドを作成。
app/helpers/sessions_helper.rb
# ユーザーを永続的セッションに記憶する def remember(user) user.remember cookies.permanent.signed[:user_id] = user.id cookies.permanent[:remember_token] = user.remember_token end
永続セッションの場合は、session[:user_id]が存在すれば一時セッションからユーザーを取り出し、それ以外の場合はcookies[:user_id]からユーザーを取り出して、対応する永続セッションにログインする必要があります。
状況によって一時セッションとcookiesを使い分けるようにcurrent_user
メソッドを修正。
app/helpers/sessions_helper.rb
# 記憶トークン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
ブラウザのcookiesを削除する手段が未実装なので (20年待てば消えますが)、ユーザーがログアウトできません。
ログアウトボタン押してもcookiesが削除されない=ログアウトできないのでテストがNGとなることを確認。
$ bundle exec rake test 24 tests, 59 assertions, 1 failures, 0 errors, 0 skips
実際にcookiesに保存されるかどうかはまだ動作見てない。それは追々。
なんか難しくなってきたなぁ、という印象。。。「記憶トークン」という単語が見慣れないからかも?
今日の作業時間は【32分】。
次は「8.4.3 ユーザーを忘れる」から。