401错误关键在响应头WWW-Authenticate字段,它明确指示认证方案、realm及错误原因;若该头缺失或与Bearer不匹配,则需检查认证位置(如X-Auth-Token)、Token有效性、变量引用、时钟偏移或网关预处理等隐蔽因素。

Postman里填了Bearer Token却返回401,先看响应头里的WWW-Authenticate
401不是“你没给token”,而是“你给的token不被当前接口认”。真正关键的诊断线索藏在响应头里——WWW-Authenticate字段。比如你收到:
HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer realm="api.example.com", error="invalid_token", error_description="The access token expired"
这行就直接告诉你三件事:后端只接受Bearer方案、token已过期、realm是api.example.com。但多数人会跳过它,转头重粘一遍token。
- 务必打开Postman Console(View → Show Postman Console),点开对应请求的Response Headers,找
WWW-Authenticate - 如果这个头根本没出现,说明后端压根没走标准认证流程——可能是用
X-Auth-Token、Api-Key等自定义头,或校验逻辑写在中间件里但没返回规范头 - 若头里写的是
Basic realm=...,那你填Bearer Token就是错的,得切到Basic Auth并填用户名密码
Token位置填错:Authorization头 ≠ 所有接口都认的“标准位置”
很多团队不走RFC标准,硬性要求token必须放在某个自定义Header里,比如X-Auth-Token或Authorization-Token。这时你在Postman的Authorization标签页里选Bearer Token,等于把token塞进Authorization: Bearer xxx,但服务端压根不读这个头。
- 查接口文档,确认认证字段名——注意大小写和中划线,
X-AUTH-TOKEN和X-Auth-Token在部分服务器上不等价 - 在Postman的
Headers选项卡里手动添加键值对:X-Auth-Token→{{access_token}}(别忘了用变量) - 如果文档写“token需放在Query参数中”,那就去
Params里加token=xxx,而不是碰Authorization标签页 - 某些老旧Spring Security配置会忽略
Authorization头,除非你显式启用http.authorizeHttpRequests()并配置requestMatchers("/api/**").authenticated()
Token本身有效,但被服务端拒绝的隐蔽原因
jwt.io解码显示exp正常、iss和aud也匹配,还是401?问题可能出在服务端校验链路上。
TokenGX Cap 验证码【代码集成】技能 —— 面向开发场景,提供前端组件和后端验证的代码模板,帮助用户将 Cap 无感验证码快速集成到网站或应用中。适用场景:注册登录防刷、表单提交保护、API 接口防爬、发短信/邮件防滥用等。支持前端(HTML/React/Vue/Next.js)和后端(Node.js/Python/PHP/Go)全栈集成。触发词:集成验证码、添加人机验证、CAPTCHA 集成、cap widget、验证码前端、验证码后端、防刷表单等。与 tokengx-cap-admin(服务
- Token签名密钥不一致:开发环境用
HS256配了硬编码密钥,但测试环境实际用的是RS256+ 公私钥对,导致验签失败 - 时钟偏移(Clock Skew):服务端时间比客户端快/慢超过5分钟,JWT库默认拒绝
nbf或exp偏差过大的token;Spring Security默认容忍60秒,可调但需主动配置 - IP或User-Agent白名单:某些风控中间件会校验请求来源,Postman发请求的
User-Agent是PostmanRuntime/7.40.0,可能被规则拦截 - Redis缓存失效:token虽未过期,但服务端查
blacklist:xxx发现已被登出或刷新,直接拒掉
环境变量和变量引用写错,导致token根本没传出去
你以为填了{{access_token}}就万事大吉,其实Postman变量系统很脆,一不留神就空着发请求。
- 检查变量是否定义在正确作用域:全局变量(Globals)、环境变量(Environments)、集合变量(Collection Variables)优先级不同,
{{access_token}}在环境里定义,就得确保右上角环境切换器选中了那个环境 - 变量名拼写错误:比如定义的是
auth_token,请求里却写{{access_token}},Postman不会报错,只会静默替换为空字符串 - 登录接口Tests脚本里没正确提取:用
pm.environment.set("access_token", jsonData.token),但响应体其实是{"data": {"token": "xxx"}},得写成jsonData.data.token - 在Authorization标签页选
Bearer Token时,输入框里不能写Bearer {{access_token}}——Postman会自动加Bearer前缀,重复导致Bearer Bearer xxx
最常被忽略的一点:某些API网关(如Kong、Apigee)会对Authorization头做预处理,比如剥离Bearer 再转发,而你的服务端又期望原样接收,这种错位只能靠抓包确认真实到达的头内容。










