注销时出错:未定义的方法 'invalidate_token'
Error on Logout: undefined method 'invalidate_token'
我正在 Rails 5 API 上构建身份验证,但我在注销部分遇到了问题。我正在点击 /logout
路线并收到 500 错误读数 NoMethodError: undefined method 'invalidate_token' for nil:NilClass>
,然后它引用了我的 sessions_controller。我的 sessions_controller 引用了用户模型中声明的注销方法中的 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 并实际上使登录的用户令牌无效。
这是因为您的current_user是nil.You,在请求注销时必须发送auth_token。使用此 auth_token 您必须获取用户,以便您可以更新该用户 -- nil auth_token。如果找不到用户,那么您必须处理这种情况下的异常,因为您正在请求无效 auth_token 或用户可能不存在于您的数据库中。
你还需要更正这个
def logout
current_user.invalidate_token
end
抱怨 @current_user
是 nil
,因此在 @current_user
上使用 invalidate_token
之前,请确保 @current_user
不是 nil
。
我猜你在application_controller
中使用current_user
method
,returns @current_user
所以替换
def logout
@current_user.invalidate_token
end
和
def logout
current_user.invalidate_token
end
您在 authenticate_token
中获取用户记录时正在执行 find_by
。如果没有找到记录,则返回 nil
。
您的数据有误,或者您的 header 无效。
我正在 Rails 5 API 上构建身份验证,但我在注销部分遇到了问题。我正在点击 /logout
路线并收到 500 错误读数 NoMethodError: undefined method 'invalidate_token' for nil:NilClass>
,然后它引用了我的 sessions_controller。我的 sessions_controller 引用了用户模型中声明的注销方法中的 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 并实际上使登录的用户令牌无效。
这是因为您的current_user是nil.You,在请求注销时必须发送auth_token。使用此 auth_token 您必须获取用户,以便您可以更新该用户 -- nil auth_token。如果找不到用户,那么您必须处理这种情况下的异常,因为您正在请求无效 auth_token 或用户可能不存在于您的数据库中。 你还需要更正这个
def logout
current_user.invalidate_token
end
抱怨 @current_user
是 nil
,因此在 @current_user
上使用 invalidate_token
之前,请确保 @current_user
不是 nil
。
我猜你在application_controller
中使用current_user
method
,returns @current_user
所以替换
def logout
@current_user.invalidate_token
end
和
def logout
current_user.invalidate_token
end
您在 authenticate_token
中获取用户记录时正在执行 find_by
。如果没有找到记录,则返回 nil
。
您的数据有误,或者您的 header 无效。