You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Rails 5中用Devise和JWT实现用户认证,我遗漏了什么?

Rails 5 + Devise + JWT 认证的必要补充配置步骤

我帮你梳理下Rails 5里用Devise+JWT做用户认证时容易遗漏的关键步骤,都是实战中踩过坑的点:

  • 安装适配的JWT Gem
    别自己手动写JWT逻辑啦,官方适配的devise-jwt能省超多事。先在Gemfile里加:

    gem 'devise-jwt'
    

    然后跑bundle install完成安装。

  • 完善User模型的Devise配置
    确保你的User模型已经包含Devise的核心模块,还要加上JWT相关的配置,比如:

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

    这里的jwt_revocation_strategy是用来处理token失效的(比如用户登出),后面会说具体实现。

  • 生成并配置JWT初始化文件
    跑这个命令生成官方的配置模板:

    rails generate devise:jwt:install
    

    生成的config/initializers/devise_jwt.rb里,记得把密钥改成环境变量(别硬编码!),还能设置token过期时间、触发分发/失效的路由:

    Devise::JWT.configure do |config|
      config.secret_key = ENV['DEVISE_JWT_SECRET_KEY'] || Rails.application.credentials.devise_jwt_secret_key
      config.expiration_time = 3600 # 1小时过期,按需调整
      config.dispatch_requests = [['POST', %r{^/login$}]]
      config.revocation_requests = [['DELETE', %r{^/logout$}]]
    end
    
  • 实现JWT黑名单策略(可选但必做)
    要是没有黑名单,用户登出后token还能继续用,太不安全了。先生成黑名单模型:

    rails generate model JwtBlacklist jti:string exp:datetime
    rails db:migrate
    

    然后在模型里实现revocation的逻辑:

    class JwtBlacklist < ApplicationRecord
      include Devise::JWT::RevocationStrategies::Blacklist
      self.table_name = 'jwt_blacklists'
    end
    
  • 路由配置要到位
    除了你写的authenticate_user路由,还要配置好登录、登出和受保护路由:

    # config/routes.rb
    devise_for :users, skip: [:session, :password, :registration, :confirmation]
    post '/login', to: 'authentication#authenticate_user'
    delete '/logout', to: 'authentication#logout'
    
    # 保护API路由示例
    namespace :api do
      namespace :v1 do
        before_action :authenticate_user!
        resources :posts
      end
    end
    
  • 完善AuthenticationController的方法
    你之前的payload方法没写完,补上标准的JWT生成逻辑:

    private
    def payload(user)
      return nil unless user&.id
      {
        auth_token: JWT.encode(
          { user_id: user.id, exp: 1.day.from_now.to_i },
          Devise::JWT.secret_key
        ),
        user: { id: user.id, email: user.email }
      }
    end
    

    再加个登出方法,把当前token加入黑名单:

    def logout
      token = request.headers['Authorization']&.split(' ')&.last
      return render json: { errors: ['No token provided'] }, status: :bad_request unless token
    
      jwt_payload = JWT.decode(token, Devise::JWT.secret_key).first
      JwtBlacklist.create!(jti: jwt_payload['jti'], exp: Time.at(jwt_payload['exp'].to_i))
      render json: { message: 'Logged out successfully' }, status: :ok
    end
    
  • CORS配置(前后端分离必做)
    如果前端是单独的应用,得装rack-cors解决跨域问题:

    # Gemfile
    gem 'rack-cors'
    

    然后在config/initializers/cors.rb里配置:

    Rails.application.config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins 'your-frontend-domain.com' # 生产环境别用*
        resource '*',
          headers: :any,
          methods: [:get, :post, :put, :patch, :delete, :options, :head],
          expose: ['Authorization']
      end
    end
    
  • 测试认证流程
    别光写代码,用curl或Postman测一遍:

    1. 登录:POST /login带email和password,看是否返回auth_token
    2. 访问受保护路由:带上Authorization: Bearer <token>,确认能正常返回数据
    3. 登出:DELETE /logout带token,之后再用这个token请求应该返回401

内容的提问来源于stack exchange,提问作者adam tropp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:56:59