Next.js:getServerSideProps调用API时Bearer Token报403错误排查
问题原因分析
从你提供的错误日志能直接定位问题:Authorization请求头里的token被额外的双引号包裹,导致后端JWT验证失败,返回403权限错误。
看日志里的关键行:
Authorization: 'Bearer "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcnVuYWJoIiwiZXhwIjoxNjY0NTQwODYwLCJpYXQiOjE2NjQ1MzM2NjB9.Ib3X-6TMyQ3YfoGz-PuS4hehzuHq-N6XHwzLF6cXD2U"'
正常的Bearer Token格式应为Bearer <纯token字符串>,这里的token被双引号括起来,后端验证逻辑会判定为无效token,直接拒绝请求。
问题根源
- 登录成功后,你用
JSON.stringify(response.data)将token转为JSON字符串,原本的纯token(如abc123)被自动加上了双引号,变成"abc123"。 - 带双引号的token通过URL query参数传递,在
getServerSideProps中直接获取的context.query.auth就是带引号的字符串。 - 拼接Authorization头时,最终生成了不符合规范的
Bearer "xxx"格式。
解决步骤
1. 修复token传递逻辑
在登录的handleSubmit中,不需要用JSON.stringify,直接传递原始token值即可(response.data本身就是纯token字符串):
// 原代码 query: { auth: JSON.stringify(response.data) }, // 修改后 query: { auth: response.data },
如果response.data是包含token的对象(如{ token: "xxx" }),则取对应字段:
query: { auth: response.data.token },
2. 简化组件内的token读取
修改后,Allcoupons组件中拿到的router.query.auth就是纯token,无需再用JSON.parse:
// 原代码 const val = router.query.auth ? JSON.parse(router.query.auth) : {}; // 修改后 const val = router.query.auth || "";
3. 优化token存储方式(重要)
绝对不要通过URL query传递token,URL会被记录在浏览器历史、服务器日志中,存在严重安全风险。推荐两种安全方案:
- HttpOnly Cookie:后端
/authenticate接口返回token时,将其设置为HttpOnly Cookie(前端无法读取,但浏览器会自动携带到同域名请求),getServerSideProps可直接从context.req.cookies获取token。 - localStorage(仅客户端渲染):登录成功后将token存入
localStorage,客户端发起请求时从中读取并添加到请求头。但该方式在SSR的getServerSideProps中无法直接读取,需调整数据获取逻辑到客户端。
验证修复效果
修改后,getServerSideProps中的Authorization头会变成规范格式:
{ headers: { Authorization: `Bearer ${token}` } }
日志里的Authorization头将显示为:
Authorization: 'Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhcnVuYWJoIiwiZXhwIjoxNjY0NTQwODYwLCJpYXQiOjE2NjQ1MzM2NjB9.Ib3X-6TMyQ3YfoGz-PuS4hehzuHq-N6XHwzLF6cXD2U'
后端即可正常验证JWT token,返回预期数据。
内容的提问来源于stack exchange,提问作者MagnusEffect
相关产品推荐
相关产品推荐

