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

部署到Heroku的Rails API+React应用JWT请求出现401未授权错误

解决Rails API + React部署Heroku后JWT 401 Unauthorized问题

从你的日志和代码细节来看,核心问题是生产环境下decoded_token返回了nil,导致logged_in?判定为false,触发了authorized过滤器返回401。下面是一步步的排查和解决思路:

1. 优先检查Heroku环境变量配置

你的JWT编码和解码完全依赖ENV['jwt_encode_string'],开发环境你本地的.env文件里肯定配置了这个密钥,但Heroku不会自动同步本地环境变量,这是最常见的坑:

  • 打开终端,运行命令设置Heroku环境变量(替换成你本地用的密钥内容):
    heroku config:set jwt_encode_string=你的专属密钥内容
    
  • 验证是否设置成功:
    heroku config:get jwt_encode_string
    
    必须确保输出的内容和本地.env里的完全一致,哪怕多一个空格都会导致解码失败。

2. 统一Authorization头的格式

虽然开发环境正常,但生产环境可能因为token传输/存储的细微差异导致格式问题。建议按照JWT标准格式调整:

  • 修改前端fetch请求的headers,添加Bearer 前缀:
    headers:{
      "Authorization": `Bearer ${localStorage.token}`,
      "Content-Type":"application/json",
      Accept:"application/json"
    },
    
  • 对应修改Rails后端的auth_header方法,兼容前缀提取token:
    def auth_header
      # 提取Bearer后的token部分,兼容有无前缀的情况
      request.headers['Authorization']&.split(' ')&.last
    end
    

3. 手动验证JWT token的有效性

可以在本地模拟生产环境生成token,直接测试后端验证逻辑:

  • 打开本地Rails控制台(确保本地环境变量和Heroku一致),生成测试token:
    payload = { customer_id: 1 } # 替换成你系统中存在的真实用户ID
    token = JWT.encode(payload, ENV['jwt_encode_string'], 'HS256')
    puts token
    
  • 用curl或Postman发送请求到Heroku API,带上这个token:
    curl -X POST https://health-and-fit-store-api.herokuapp.com/cart_products \
      -H "Authorization: Bearer 刚才生成的token" \
      -H "Content-Type: application/json" \
      -d '{"productId": 1}'
    

如果这个请求成功,说明后端验证逻辑没问题,问题出在前端存储或发送token的环节;如果还是401,那肯定是后端密钥配置有误。

4. 打印JWT解码错误详情

修改decoded_token方法,把解码错误日志打出来,方便精准定位:

def decoded_token
  if auth_header
    token = auth_header
    begin
      JWT.decode(token, ENV['jwt_encode_string'], true, algorithm: 'HS256')
    rescue JWT::DecodeError => e
      Rails.logger.error "JWT解码失败: #{e.message}"
      nil
    end
  end
end

部署后重新触发请求,然后查看Heroku实时日志:

heroku logs --tail

这样能看到具体的错误原因,比如密钥不匹配、token过期、格式损坏等。

5. 确认跨域CORS配置

虽然开发环境正常,但生产环境的跨域规则可能需要调整,确保Rails API允许前端域名的请求,并暴露Authorization头:
在config/initializers/cors.rb中配置:

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins '你的前端Heroku域名' # 比如 'https://health-and-fit-store-frontend.herokuapp.com'
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head],
      expose: ['Authorization'] # 确保前端能获取到Authorization头
  end
end

按照上面的步骤排查,大概率能解决问题——最常见的原因就是Heroku环境变量设置错误,导致JWT解码失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:36:47