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

Ruby on Rails API JWT认证404及无效凭证问题求助

排查Ruby on Rails JWT认证访问/todos接口的问题

先针对你遇到的两个错误逐一拆解排查:

一、「Couldn't find User without an ID」错误原因及修复

这个错误的核心是查找用户时没有传入正确的user_id参数,常见场景:

  • 你可能在authenticate_user!方法里错误地用了User.find(params[:id])来获取用户,但/todos接口的请求参数里并没有id,导致找不到用户。
  • JWT解码后的payload里没有正确包含user_id字段,或者你提取字段时拼写错误(比如写成user而非user_id)。

正确的用户查找逻辑示例

# app/controllers/application_controller.rb
private
def authenticate_user!
  auth_header = request.headers['Authorization']
  return render_unauthorized unless auth_header&.start_with?('Bearer ')

  token = auth_header.split(' ').last
  begin
    # 解码JWT并提取payload中的user_id
    payload = JWT.decode(token, Rails.application.secrets.secret_key_base, true, algorithm: 'HS256')[0]
    # 从payload取user_id查找用户,而非params
    @current_user = User.find(payload['user_id'])
  rescue ActiveRecord::RecordNotFound
    render_unauthorized
  end
end

def render_unauthorized
  render json: { error: 'invalid credentials' }, status: :unauthorized
end

二、「invalid credentials」错误原因及排查

这个错误通常是JWT验证失败导致,按优先级排查:

  1. 请求头Token格式错误:确保前端传递的Authorization头是Bearer <你的token>格式,很多时候会漏掉Bearer 前缀,导致解码失败。
  2. JWT密钥不一致:检查生成Token和验证Token时使用的secret key是否完全相同。比如生成时用了ENV['JWT_SECRET'],验证时却用了Rails.application.secrets.secret_key_base,会直接导致解码失败。
  3. Token已过期:查看生成Token时设置的exp(过期时间)字段,是否过期时间过短,导致请求时Token已失效。
  4. Token传递错误:检查前端传递的Token是否完整,有没有被截断、复制错误,或者在传递过程中被转义。

辅助排查:添加日志定位问题

在authenticate_user!方法中加入日志,打印关键数据,能快速定位哪一步出错:

private
def authenticate_user!
  auth_header = request.headers['Authorization']
  Rails.logger.debug "Received Auth Header: #{auth_header}" # 查看请求头是否正确
  return render_unauthorized unless auth_header&.start_with?('Bearer ')

  token = auth_header.split(' ').last
  Rails.logger.debug "Extracted Token: #{token}" # 查看提取的Token是否完整
  begin
    payload = JWT.decode(token, Rails.application.secrets.secret_key_base, true, algorithm: 'HS256')[0]
    Rails.logger.debug "Decoded Payload: #{payload}" # 查看payload是否包含user_id
    @current_user = User.find(payload['user_id'])
    Rails.logger.debug "Found User: #{@current_user.inspect}" # 查看用户是否找到
  rescue JWT::DecodeError => e
    Rails.logger.error "JWT Decode Error: #{e.message}" # 打印解码具体错误
    render_unauthorized
  rescue ActiveRecord::RecordNotFound
    Rails.logger.error "User not found with ID: #{payload['user_id']}"
    render_unauthorized
  end
end

三、额外检查点

  • 确认注册/登录接口生成Token时,payload中确实包含user_id字段,比如生成Token的代码:
def generate_token(user)
  JWT.encode({ user_id: user.id, exp: 24.hours.from_now.to_i }, Rails.application.secrets.secret_key_base)
end
  • 确保TodosController继承了ApplicationController,从而触发before_action :authenticate_user!的验证逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 12:22:43