チェックボックスを作るとトークンを作らなければならないらしい。
1.記憶トークン用のカラムを用意
(新たなデータベースの空欄を作る)
2.ランダムな文字列を生成し、ハッシュ化する
(自分にもわからないように文字列を散らす)
user.rb
# ランダムなトークンを返す
def User.new_token
SecureRandom.urlsafe_base64
# 文字列を生成する
end
# 永続セッションのためにユーザーをデータベースに記憶する
def remember
self.remember_token = User.new_token
# ランダムな文字列を返す
self.update_attribute(:remember_digest, User.digest(remember_token))
# ランダムな文字列をハッシュ化させ、remember_digestのカラムに納める
end
3.ハッシュ化した値を、データベースのカラムに保存する
sessions_controller
remember user
#データベースにハッシュ化された 文字列記憶させる
# 永続セッションのためにユーザーをデータベースに記憶する
def remember
self.remember_token = User.new_token
# ランダムな文字列を返す
update_attribute(:remember_digest, User.digest(self.remember_token))
# データベースの値を複数同時に更新
# ランダムな文字列digestでをハッシュ化させる
# remember_digest(データベース)のカラムに記憶させる
4.ブラウザのcookiesに、暗号化したIDとTokenを保存する
(ブラウザの中にあるcookiesに保存する)
sessions_helper
# ユーザーのセッションを永続的にする
def remember(user)
#userクラスのrememberメソッドとは違う
#こっちは引数を使和なければならない
user.remember
# 新たなハッシュ化された文字列を生成
cookies.permanent.signed[:user_id] = user.id
# cookiesにID番号を返す
# .signed ure idを暗号化、複合化する
cookies.permanent[:remember_token] = user.remember_token
# rememberは仮想の何かだから次になんかしたら消えるので
# cookiesにトークンを保存する
end
コントローラで使うrememberメソッド
5.cookiesのIDを使って、ユーザーをデータベースから検索する。
cookeisのTokenを認証し、同一からセッションを復元する
(ブラウザの中にあるcookiesのユーザーIDとTokenから認証される)
# 渡されたトークンがダイジェストと一致したらtrueを返す
def authenticated?(remember_token)
BCrypt::Password.new(remember_digest).is_password?(remember_token)
# データベースのremember_digestとトークンのremember_token
#を照らし合わせる
end
def current_user
if (user_id = session[:user_id])
# sessionのuser_idを取り出し、返す
# nil,falseでないかをチェック つまり空では無いか
@current_user ||= User.find_by(id: user_id)
#一回だけデータベースに問い合わせる
elsif (user_id = cookies.signed[:user_id])
# 暗号化されたクッキーのユーザーIDがあれば
user = User.find_by(id: user_id)
# ユーザーIDでユーザーを検索する
if user && user.authenticated?(cookies[:remember_token])
# ユーザーが存在し、データベースとクッキーのトークンが一致したら
log_in user
#log_inメソッドでう
@current_user = user
#任意のデータベースを取得する
# メモ化する
end
end
end
Error:
UserTest#test_authenticated?_should_return_false_for_a_user_with_nil_digest:
BCrypt::Errors::InvalidHash: invalid hash
app/models/user.rb:43:in `new'
app/models/user.rb:43:in `authenticated?'
#authenticatedで失敗
test/models/user_test.rb:71:in `block in <class:UserTest>'
# 渡されたトークンがダイジェストと一致したらtrueを返す
def authenticated?(remember_token)
return false if remember_digest.nil?
# remember_digestが空ならばfalseを返す
# 先にreturnをすることでエラーを起こさないようにする
# remember_tokenが空(nil)だから
BCrypt::Password.new(remember_digest).is_password?(remember_token)
# データベースのremember_digestとトークンのremember_token
#を照らし合わせる
end
勉強の内容
1.チェックボックスをLog inフォームに設置
2.CSSでデザインを改善
3.params[:session][:remember_me]をチェックして、
チェックされていたらrememberメソッドを、
そうでなければforgeメソッドを使用
def current_user
if (user_id = session[:user_id])
# sessionのuser_idを取り出し、返す
# nil,falseでないかをチェック つまり空では無いか
@current_user ||= User.find_by(id: user_id)
#一回だけデータベースに問い合わせる
elsif (user_id = cookies.signed[:user_id])
# 暗号化されたクッキーのユーザーIDがあれば
raise
# 強制的にエラーを起こす
user = User.find_by(id: user_id)
# ユーザーIDでユーザーを検索する
if user && user.authenticated?(cookies[:remember_token])
# ユーザーが存在し、データベースとクッキーのトークンが一致したら
log_in user
#log_inメソッドでう
@current_user = user
#任意のデータベースを取得する
# メモ化する
end
end
end
バグの見つけ方
rails testで成功したらテストで確認できていない
書き損じがあるがこんな感じで進んでいくらしい。