我正在使用Rails Tutorial并且遇到了第8章 - 关于登录会话的问题。当我提交应该创建新会话的电子邮件/密件组合时,会出现错误。
这是错误:
NoMethodError in SessionsController#create
undefined method `remember_token=' for #<User:0x0000010b454f50>
Extracted source (around line #435):
else
match = match_attribute_method?(method.to_s)
match ? attribute_missing(match, *args, &block) : super
end
end
从那里我在会话控制器中查看create。我试着看看我在哪里调用remember_token方法。
会话控制器:
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
#if 1 then remember, else forget
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
remember user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
#call log_out helper method
log_out if logged_in?
redirect_to root_url
end
end
我致电remember
这看起来很重要。这是会话助手:
module SessionsHelper
#Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
def remember(user)
#generate a new token and provide the encrypted hash
user.remember
cookies.permanent.signed[:user_id]=user.id
cookies.permanent[:remember_token]=user.remember_token
end
def current_user
#if session user id exists, then set to user_id and then...
if (user_id = session[:user_id])
#set @current_user to the correct user account
@current_user||= User.find_by(id: user_id)
#else, if signed cookie user id exists, set to user_id and then...
elsif (user_id = cookies.signed[:user_id])
#set user to the correct user account and...
user = User.find_by(id: user_id)
#if user is authenticated, then log them in and set @current_user to user
if user && user.authenticated?(cookies[:remember_token])
log_in user
@current_user = user
end
end
end
def logged_in?
!current_user.nil?
end
#Forgets a persistent session
def forget(user)
user.forget
cookies.delete(:user_id)
cookies.delete(:remember_token)
end
def log_out
forget(current_user)
session.delete(:user_id)
@current_user = nil
end
end
看起来像是密钥 - cookies.permanent[:remember_token]=user.remember_token
。
但我不知道如何定义remember_token方法。当我浏览教程时,我没有看到任何描述remember_token的方法。我得到的最接近的是用户模型(方法称为remember
):
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
belongs_to :courses
belongs_to :lessons
validates :first_name, presence: true, length: { maximum: 50 }
validates :last_name, presence: true, length: { maximum: 50 }
validates :email, presence: true, length: { maximum: 255 },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, length: { minimum: 6}
#Returns the hash digest of the given string
def User.digest(string)
cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
BCrypt::Password.create(string, cost: cost)
BCrypt::Password.create(string, cost: cost)
end
#Returns a random token
def User.new_token
SecureRandom.urlsafe_base64
end
#creates a new token (random string) then encypts it by returning a hash
def remember
self.remember_token = User.new_token
update_attribute(:remember_digest, User.digest(remember_token))
end
#Returns true if the given token matches the digest
def authenticated?(remember_token)
return false if remember_digest.nil?
BCrypt::Password.new(remember_digest).is_password?(remember_token)
end
#forgets a user
def forget
update_attribute(:remember_digest, nil)
end
end
我是否了解会话控制器,会话助手和用户模型之间的相互作用?相互作用是不是设置正确 - 这是抛出错误?我不明白为什么它不起作用......
背景: 本教程有意避免将remember_token作为安全功能放在数据库中。所以这不是问题。
答案 0 :(得分:-1)
问题在于会话控制器 - 我没有理解三元运算符并重复了一些功能。这是原始的创建方法:
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
#if 1 then remember, else forget
params[:session][:remember_me] == '1' ? remember(user) : forget(user)
remember user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
这个位remember user
是多余的。
三元params[:session][:remember_me] == '1' ? remember(user) : forget(user)
表示如果params[:session][:remember_me]
为1,则remember(user)
为其他forget(user)
。
然后调用remember user
(与remember(user)
相同)我执行了两次相同的操作,导致错误。