使用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:全局保护所有接口(适合绝大多数接口需要登录的场景)
如果你的应用大部分接口都需要登录权限,可以直接把校验加到全局父控制器,再给登录、注册等不需要权限的接口跳过校验即可:
- 修改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
- 在自定义的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
相关产品推荐
相关产品推荐

