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

使用Devise+JWT时如何限制仅已认证用户可访问控制器方法

解决方案

你当前的代码中process_token仅负责解析请求头中的JWT并设置当前用户ID,没有强制要求请求必须携带有效token,因此未带token的请求也能正常访问接口,按以下两种方案配置即可实现拦截:


方案1:仅保护TransactionsController接口

直接在TransactionsController中添加前置校验动作即可,所有请求该控制器的接口都会先校验是否携带有效token:

class TransactionsController < ApplicationController
  # 新增这一行即可完成保护
  before_action :authenticate_user!

  def create
    transaction = Transaction.new(transaction_params)

    if transaction.save
      render json: transaction
    else
      render json: { errors: "transaction is invalid" }, status: :unprocessable_entity
    end
  end

  def index
    transactions = Transaction.all.order(created_at: :desc)
    render json: transactions
  end

  def destroy
    transaction = Transaction.find(params[:id])
    transaction&.destroy
    render json: { message: "transaction deleted"}
  end

  def transaction_params
    params.require(:transaction).permit(:payer_id, :recipient_id, :amount)
  end
end

方案2:全局保护所有接口(适合绝大多数接口需要登录的场景)

如果你的应用大部分接口都需要登录权限,可以直接把校验加到全局父控制器,再给登录、注册等不需要权限的接口跳过校验即可:

  1. 修改ApplicationController添加全局校验:
class ApplicationController < ActionController::API
  respond_to  :json
  before_action :process_token
  # 新增全局登录校验
  before_action :authenticate_user!

  def authenticate_user!(options = {})
    head :unauthorized unless signed_in?
  end

  def signed_in?
    @current_user_id.present?
  end

  def current_user
    @current_user ||= super || User.find(@current_user_id)
  end

  def process_token
    if request.headers['Authorization'].present?
      begin
        jwt_payload = JWT.decode(request.headers['Authorization'].split(' ')[1].remove('"'), Rails.application.secrets.secret_key_base).first
        @current_user_id = jwt_payload['id']
      rescue JWT::ExpiredSignature, JWT::VerificationError, JWT::DecodeError
        head :unauthorized
      end
    end
  end
end
  1. 在自定义的Devise注册、会话控制器中跳过校验,避免登录注册接口被拦截:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
  skip_before_action :authenticate_user!
  # 原有逻辑保持不变
end

# app/controllers/sessions_controller.rb
class SessionsController < Devise::SessionsController
  skip_before_action :authenticate_user!
  # 原有逻辑保持不变
end

测试注意事项

接口请求时需要在请求头携带Authorization: Bearer <登录接口返回的JWT token>,否则会直接返回401未授权状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 02:48:04