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

React使用Fetch调用Spring Security OAuth接口返回401错误排查

解决React Fetch调用Spring Security OAuth接口返回401的问题

嗨,我帮你梳理下这个问题——Postman能正常请求但Fetch返回401,大概率是请求里的细节没和Postman对齐,咱们一步步排查:

1. 请求体里的&是关键错误

你拼接请求体时用了&,这是HTML的转义字符,但在JavaScript里直接写会被当成字符串的一部分。服务器解析时会把&password认成一个参数名,而不是参数分隔符,自然拿不到正确的密码,直接返回未授权。

修正后的手动拼接写法:

body: `username=${data.username}&password=${data.password}&grant_type=password`

更稳妥的是用URLSearchParams构建请求体,它能自动处理特殊字符编码(比如用户名/密码里有&、=这类符号时):

const params = new URLSearchParams();
params.append('username', data.username);
params.append('password', data.password);
params.append('grant_type', 'password');

fetch("http://localhost:8080/oauth/token", {
  method: 'POST',
  headers: {
    'Authorization': 'Basic bXlhcHA6Y2xpZW50c2VjcmV0', // 替换成你实际的Base64编码
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: params
})

2. Authorization头的Base64编码可能不完整

你当前的Authorization头是Basic bXlhcHA6,这是myapp:(client_id为myapp,client_secret为空)的Base64编码,但注意Base64编码必须是4的倍数,末尾的填充字符==不能省略。如果你的client_secret不为空,一定要把client_id:client_secret完整字符串做Base64编码。

正确生成方式:
可以在代码里用浏览器原生的btoa()函数生成:

// 替换成你的真实client_id和client_secret
const authString = `${clientId}:${clientSecret}`;
const authBase64 = btoa(authString);
// 之后在headers里用 `Basic ${authBase64}`

比如client_id是myapp、client_secret是clientsecret的话,编码后应该是bXlhcHA6Y2xpZW50c2VjcmV0,而不是不完整的bXlhcHA6。

3. 跨域场景的额外检查

如果你的React项目和后端不在同一个端口(比如React跑在3000,后端在8080),要确保Spring Security配置了正确的CORS规则:

  • 允许你的React域名(比如http://localhost:3000)作为请求源
  • 允许携带Authorization、Content-Type这些请求头
  • 允许POST请求方法

快速验证步骤

  1. 先把请求体里的&换成&测试,这是最可能的问题点
  2. 打开浏览器控制台的Network面板,对比实际发送的请求头、请求体和Postman里的内容,看有没有差异
  3. 确认Authorization头的编码和Postman自动生成的一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 04:18:54