部署到Heroku的Rails API+React应用JWT请求出现401未授权错误
从你的日志和代码细节来看,核心问题是生产环境下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
相关产品推荐
相关产品推荐

