使用Axios发送Content-Type为x-www-form-urlencoded的POST请求返回401未授权
解决Axios发送x-www-form-urlencoded POST请求返回401的问题
我之前也踩过这个一模一样的坑!Postman能正常拿到token,但Axios一发就返回401,核心问题大概率是请求体格式没处理对——Postman会自动帮你把x-www-form-urlencoded类型的参数转成符合要求的字符串格式,但Axios默认不会直接处理对象类型的请求体,导致服务端解析不到正确的参数,从而返回未授权。
下面是几个针对性的解决方案,按优先级尝试:
1. 正确格式化请求体
x-www-form-urlencoded类型的请求体需要是key1=value1&key2=value2这样的字符串,而不是JSON对象。你可以用两种方式处理:
方式一:使用原生URLSearchParams
这是最不需要额外依赖的方法,直接用浏览器/Node.js原生API包装参数:
// 构建符合格式的请求体 const data = new URLSearchParams(); data.append('grant_type', 'client_credentials'); // 如果还有其他必填参数(比如部分场景需要client_id/client_secret),也在这里append axios.post(`${baseURI}/protocol/openid-connect/token`, data, { headers: { "Authorization": "Basic " + token, // 确保这里的token是client_id:client_secret的base64编码 "Content-Type": "application/x-www-form-urlencoded" } // 先暂时去掉withCredentials: true,排查是否是cookie干扰 }) .then(response => { AUTH_TOKEN = response.data.access_token; console.log(response.data); }) .catch(error => { console.log(error.response?.data || error.message); });
方式二:用qs库序列化对象
如果你的项目已经依赖了qs(很多前端项目都会用到),可以直接用它把对象转成符合要求的字符串:
import qs from 'qs'; const data = { grant_type: 'client_credentials' }; axios.post(`${baseURI}/protocol/openid-connect/token`, qs.stringify(data), { headers: { "Authorization": "Basic " + token, "Content-Type": "application/x-www-form-urlencoded" } }) .then(response => { AUTH_TOKEN = response.data.access_token; console.log(response.data); }) .catch(error => { console.log(error.response?.data || error.message); });
2. 检查Authorization头的正确性
Basic Auth的token生成规则是:client_id:client_secret这个字符串经过Base64编码。你可以手动验证一下:
- 把你生成的
token(去掉前面的"Basic ")用Base64解码,看是不是正好是你的client_id:你的client_secret - 注意编码时要确保字符串是UTF-8格式,避免特殊字符导致编码错误(比如client_secret里有特殊符号的话,要确保转义正确)
3. 排查withCredentials的影响
withCredentials: true会让请求带上浏览器的cookie,但很多OAuth2的client_credentials模式不需要cookie,甚至额外的cookie会干扰服务端的验证逻辑。建议先把这个配置去掉,测试是否能正常获取token,如果可以再考虑是否需要保留。
最后验证小技巧
打开浏览器的Network面板,对比Axios发送的请求和Postman里的请求:
- 看Request Headers里的Authorization头是否完全一致
- 看Request Payload是否是
grant_type=client_credentials这样的字符串(而不是JSON格式)
只要这两处和Postman完全匹配,基本就能解决问题了!
内容的提问来源于stack exchange,提问作者lasith eshan
相关产品推荐
相关产品推荐

