【问题标题】:What's the impact of sequence between cookies and session when implementing "current_user"?实现“current_user”时,cookie 和 session 之间的顺序有什么影响?
【发布时间】:2018-01-24 05:33:05
【问题描述】:

我正在学习如何使用会话和 cookie 构建简单的身份验证功能。 我有一个User 模型,然后是sessions_controller。我还为 users 表创建 remember_token 列来处理“remember_me”情况。 这是相关代码:


sessions_controller

def create
  user = User.find_by_email(params[:email])

  if user && user.authenticate(params[:password])
    session[:user_id] = user.id
    if params[:remember_me]
      user.generate_token(:remember_token)
      cookies.permanent[:remember_token] = user.remember_token
    end
    redirect_to root_url
    flash[:notice] = "Logged in."
  else
    render "new"
    flash[:notice] = "Invaid email or password."
  end
end

user.rb

has_secure_password

def generate_token(column)
  self[column] = SecureRandom.urlsafe_base64
  self.save
end

application_controller

helper_method :current_user

def current_user
  if session[:user_id]
    @current_user ||= User.find(session[:user_id])
  elsif cookies[:remember_token]
    @current_user ||= User.find(cookies[:remember_token])
  end
end

上面的代码似乎工作正常。但一开始我实际上把:current_user中的代码顺序颠倒了,像这样:

def current_user
  if cookies[:remember_token]
    @current_user ||= User.find(cookies[:remember_token])
  elsif session[:user_id]
    @current_user ||= User.find(session[:user_id])
  end
end

这将引发异常:“找不到具有 'id'= some_token_here 的用户”

在这种情况下,为什么我不能首先使用 cookies[:remember_token] 找到用户。顺序重要吗?或者,如果我对会话和 cookie 的工作方式有一些误解?

【问题讨论】:

    标签: ruby-on-rails ruby session session-cookies


    【解决方案1】:

    那是因为如果你使用find,它会根据它的数据库ID找到一条记录。

    你想要的是通过remember_token 列找到,所以User.find_by(remember_token: cookies[:remember_token])

    def current_user
      if cookies[:remember_token]
        @current_user ||= User.find_by(remember_token: cookies[:remember_token])
      elsif session[:user_id]
        @current_user ||= User.find(session[:user_id])
      end
    end
    

    【讨论】:

    • 非常感谢@Robin van Dijk!这就是我想要的。
    【解决方案2】:

    From Rails Guide

    使用 find 方法,您可以检索与指定主键对应的与任何提供的选项匹配的对象。

    例如:

    # Find the client with primary key (id) 10.
    client = Client.find(10)
    # => #<Client id: 10, first_name: "Ryan">
    

    User.find(session[:user_id]) 返回所有匹配primary_key的用户

    在第二种情况下:“User.find(cookies[:remember_token])”,您应该 从“remember_token”列中搜索。

    【讨论】:

    • 我正在思考我所有的问题,我发现你的解释也很有帮助,所以谢谢! @Omurbek。
    猜你喜欢
    • 2014-06-27
    • 1970-01-01
    • 2015-07-08
    • 2014-10-03
    • 2012-12-09
    • 2012-05-11
    • 1970-01-01
    • 2023-01-18
    • 2020-07-15
    相关资源
    最近更新 更多