使用Devise做接口权限验证使用 devise-jwt gem。

安装和设置

添加devise gemGemfile

gem 'devise'
gem 'devise-jwt'

# 或者

bundle add devise
bundle add devise-jwt

安装

bundle install

配置 Devise

rails generate devise:install

配置 Devise 使用 JWT

# config/initializers/devise.rb
Devise.setup do |config|
  # 其他Devise配置...

  config.jwt do |jwt|
    jwt.secret = Rails.application.credentials.devise_jwt_secret_key
    jwt.dispatch_requests = [
      ['POST', %r{^/login$}]
    ]
    jwt.revocation_requests = [
      ['DELETE', %r{^/logout$}]
    ]
    jwt.expiration_time = 1.day.to_i
  end
end

生成User模型

rails generate devise User
rails db:migrate

User模型中添加JWT模块

class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable,
         :jwt_authenticatable, jwt_revocation_strategy: JwtDenylist
end

生成JWT拒绝列表

rails generate model JwtDenylist jti:string:index exp:datetime
rails db:migrate

在JwtDenylist中定义

class JwtDenylist < ApplicationRecord
  include Devise::JWT::RevocationStrategies::Denylist

  self.table_name = 'jwt_denylist'
end

使用JWT认证

创建处理登录和登出的控制器

class SessionsController < Devise::SessionsController
  respond_to :json

  private

  def respond_with(resource, _opts = {})
    render json: resource
  end

  def respond_to_on_destroy
    head :no_content
  end
end

更新路由

Rails.application.routes.draw do
  devise_for :users, controllers: {
    sessions: 'sessions'
  }
end

devise_for 方法根据模型中定义的模块生成所有方法。

设置保护路由

在需要保护的路由中使用before_action :authenticate_user!

class Api::BaseController < ApplicationController
  before_action :authenticate_user!
end