简体   繁体   English

令牌应该存储在Ruby On Rails中的数据库中吗?

[英]Should token store into database in Ruby On Rails?

I use the gem jwtdevise to build a user login system, 我使用gem jwtdevise构建用户登录系统,

I generate a model Authentication to check the token exist or not. 我生成一个模型身份验证以检查令牌是否存在。

follow this code: 请遵循以下代码:

models/authentication.rb 车型/ 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

controllers/user/sessions_controller.rb 控制器/用户/ 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

when I do a post request to user/sessions I will get token and user email and store it in localstorage of client, and help me to check the token is valid. 当我向user/sessions发出发布请求时,我将获得令牌和用户电子邮件,并将其存储在客户端的本地存储中,并帮助我检查令牌是否有效。

follow this code: 请遵循以下代码:

def authenticate_token
  token = Authentication.find_by_access_token(params[:token])
  head :unauthorized unless token
end 

In my question, are there ways to let token don't need to store into database? 在我的问题中,有没有办法让令牌不需要存储到数据库中?

You can decode the token and get the email stored in it, and find user by that email. 您可以解码令牌并获取存储在其中的电子邮件,然后通过该电子邮件查找用户。

Suppose you carry the token in the Authorization header, like 假设您将令牌携带在Authorization标头中,例如

Authorization: Bearer <token>

then you can define a before_action to do this: 那么您可以定义一个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

If I were you, I would put user ID in the token, not email, because ID is shorter, and faster to lookup from database, and it exposes nothing personal to the internet (note that JWT is not encrypted. It's just signed). 如果您是我,我会将用户ID放在令牌中,而不是电子邮件中,因为ID较短,并且从数据库中查找的速度更快,并且不会对Internet公开任何个人信息(请注意,JWT未加密。它只是经过签名的)。

Or you can skip all these messy things by just using knock instead of devise . 或者,您可以只使用敲门而不是devise来跳过所有这些混乱的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM