注销错误:未定义的方法'invalidate_token'

时间:2019-07-14 13:29:29

标签: ruby-on-rails ruby-on-rails-5 bcrypt

我正在Rails 5 API上构建身份验证,并且注销部分出现问题。我碰到了/logout路由,并在读取NoMethodError: undefined method 'invalidate_token' for nil:NilClass>时收到500错误,然后它引用了我的sessions_controller。我的sessions_controller在Users模型中声明的注销方法中引用了一个invalidate_token方法,当我在模型中定义错误后,为什么在控制器中未定义错误,我感到很困惑。

sessions_controller:

class SessionsController < ApiController
  skip_before_action :require_login, only: [:create], raise: false

  def create
    if (user = User.validate_login(params[:username], params[:password]))
      allow_token_to_be_used_only_once_for(user)
      send_token_for_valid_login_of(user)
    else
      render_unauthorized('Error creating the session with provided credentials')
    end
  end

  def destroy
    logout
    head :ok
  end

  private

  def send_token_for_valid_login_of(user)
    render json: { token: user.auth_token }
  end

  def allow_token_to_be_used_only_once_for(user)
    user.regenerate_auth_token
  end

  def logout
    @current_user.invalidate_token
  end
end

用户模型

class User < ApplicationRecord
  # validate unique username and email
  validates_uniqueness_of :username, :email
  has_secure_password
  has_secure_token :auth_token

  # clear token value, used to logout
  def invalidate_token
    self.update_columns(auth_token: nil)
  end

  def self.validate_login(username, password)
    user = User.find_by(username: username)
    if user && user.authenticate(password)
      user
    end
  end
end

API控制器:

class ApiController < ApplicationController
  def require_login
    authenticate_token || render_unauthorized('Access Denied: Unauthorized Access')
  end

  def current_user
    @current_user ||= authenticate_token
  end

  protected

  def render_unauthorized(message)
    errors = { errors: [detail: message] }
    render json: errors, status: :unauthorized
  end

  private

  def authenticate_token
    authenticate_with_http_token do |token|
      User.find_by(auth_token: token)
    end
  end
end

理想情况下,这应该超过注销方法,以便它可以呈现200并实际上使已登录的用户令牌无效。

3 个答案:

答案 0 :(得分:1)

有人抱怨@current_usernil,所以在invalidate_token上使用@current_user之前,请确保@current_user不是nil

我猜您在current_user中使用method application_controller返回了@current_user,所以请替换

 def logout
   @current_user.invalidate_token
 end

使用

 def logout
   current_user.invalidate_token
 end

答案 1 :(得分:1)

在获取find_by中的用户记录时,您正在执行authenticate_token。如果未找到任何记录,则返回nil

要么您的数据不正确,要么标题无效。

答案 2 :(得分:0)

这是因为您的current_user为nil。您必须在发出注销请求时发送auth_token。使用此auth_token,您必须获取用户,以便可以将其更新为-nil auth_token。如果找不到用户,则必须处理这种情况下的异常,因为您的请求使用了无效的auth_token或用户可能不在数据库中。 您还需要纠正此问题

nil <-> 7 <-> 4