我使用gem jwt
,devise
来构建用户登录系统
我生成模型身份验证以检查令牌是否存在。
请遵循以下代码:
模型/ authentication.rb
class Authentication < ApplicationRecord
def self.generate_access_token(email)
payload = {:email => email}
secret = 'secret'
token = JWT.encode payload, secret, 'HS256'
return token
end
end
控制器/用户/ sessions_controller.rb
def create
user = User.where(email: params[:email]).first
if user&.valid_password?(params[:password])
@token = Authentication.generate_access_token(user.email)
Authentication.create(access_token: @token)
authentications = {token: @token, email: user.email}
render json: authentications, status: :created
else
head(:unauthorized)
end
end
当我向user/sessions
发送请求时,我会收到令牌和用户电子邮件并将其存储在客户端的localstorage中,并帮助我检查令牌是否有效。
请遵循以下代码:
def authenticate_token
token = Authentication.find_by_access_token(params[:token])
head :unauthorized unless token
end
在我的问题中,有没有办法让令牌不需要存储到数据库中?
答案 0 :(得分:1)
您可以解码令牌并获取存储在其中的电子邮件,并通过该电子邮件找到用户。
假设您在Authorization
标题中携带令牌,例如
Authorization: Bearer <token>
然后您可以定义before_action
来执行此操作:
class ApplicationController < ActionController::API
before_action :authenticate_token
def authenticate_token
token = request.headers['Authorization'].to_s =~ /^Bearer (.*)$/i && $1
return head :unauthorized unless token
payload = JWT.decode(token, 'secret', true, algorithm: 'HS256')
user = User.find_by(email: payload['email'])
return head :unauthorized unless user
# TODO set the `user` as current_user
# How to patch devise's `current_user` helper is another story
end
end
如果我是你,我会将用户ID放在令牌中,而不是电子邮件,因为ID更短,从数据库查找更快,并且它不会向互联网公开任何个人信息(注意JWT未加密。它&# 39;刚刚签署。)
或者您可以使用knock代替devise
来跳过所有这些混乱的事情。