4. 认证与授权失败:无效、过期、签名算法错误
认证与授权失败,应该是我们在集成SDK时最常遇到的一类问题了。我在项目中有个习惯,遇到这类报错第一反应不是改代码,而是先看请求里的几个关键字段——、、签名,十有八九问题就在这三个里面。
说白了,服务器不认识你,或者不信任你了。看起来就那么几种错误码,背后原因其实挺杂的。我们一个个捋清楚。
4.1 无效
,就是你的身份凭证。服务器通过它来识别你是哪个开发者、哪个应用。
常见的报错信息:
Invalidnot foundAuthentication failed: rejected
我遇到过的原因主要有几种:
4.1.1 Key写错了或根本没填
这个看着简单,但犯的人真不少。有人直接把文档里的占位符YOUR_复制过去用了。还有人大小写写反了,或者在前面多了个空格。
嗯,这里要注意。有些SDK在初始化时会从配置文件读取Key,你得确认一下配置文件的路径对不对。我曾经在一个项目里折腾了半小时,最后发现是配置文件没被打包进资源目录。
4.1.2 Key的格式不对
不同平台的格式差异很大。有的是32位hex字符串,有的是JWT格式。有些SDK会做格式校验,格式不对直接拒绝。
我的做法:先把Key打印到日志里,肉眼看看长度和字符组成。
// 常见的格式检查
// 32位hex: 5f4dcc3b5aa765d61d8327deb882cf99
// Base64: dGhpc2lzYXRlc3RrZXk=
// JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
console.log(" length:", .length);
console.log("Prefix:", .substring(0, 8));
4.1.3 Key被禁用了或过期了
有些平台的有有效期,或者在控制台被手动停用了。你想想看,开发环境用的好好的,突然报Invalid ——我第一反应就是去后台刷新一下Key。
4.2 过期
过期比无效更让人头疼。因为过期的时机不确定,很可能在用户正用着的时候突然失效。
为什么会这样?的设计初衷就是短时效。通常有效期在几分钟到几小时不等。超过时效,服务器就认为这个不再安全,直接拒绝。
报错信息一般是:
expiredAccess invalid or expired401 Unauthorized
4.2.1 过期时间没算对
里有exp字段,存的是过期时间戳。我遇到过有人把秒级时间戳当毫秒级传,或者时区没对齐,导致刚生成就过期了。
排查方法:把解码出来看看。
// 以JWT为例,解码payload
function decodeToken() {
const payload = .split('.')[1];
const decoded = atob(payload);
console.log(" payload:", decoded);
// 看exp字段
}
4.2.2 刷新的逻辑没跑通
大多数SDK支持自动刷新,但刷新本身需要另一个Refresh 。Refresh 过期了,那自动刷新就失效了。用户就得重新登录。
我在项目中遇到过这样一个坑:刷新的接口返回了新的Access ,但没把新的Refresh 一起更新。下次再刷新时用的是旧的Refresh ,直接被拒。
正确的做法是:刷新响应里但凡有新,全部更新本地存储。
// 刷新的正确姿势
async function refreshTokens() {
const response = await fetch('/auth/refresh', {
method: 'POST',
body: JSON.stringify({ refreshToken: storedRefreshToken })
});
const data = await response.json();
// 更新本地的Access 和Refresh
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken || storedRefreshToken);
}
4.3 签名算法错误
签名算法错误,是认证失败里最隐蔽的一类。和的问题,看日志基本能定位。但签名不对,服务端通常只回一句Signature verification failed,没有更多细节。
为什么需要签名?说白了,就是确保请求内容的完整性和真实性。和只是身份凭证,签名是给每个请求盖了个章,证明这个请求是你发的、没被篡改过。
4.3.1 签名字段没拼接对
签名前需要把请求参数按指定顺序拼接成一个字符串。顺序错了,结果就完全不一样。我见过有人把参数按字母序排,但文档要求按字段顺序排。
举个例子:
// 假设文档要求拼接顺序:method + uri + timestamp + body
// 错误的做法(参数顺序错乱)
const signStr = timestamp + method + uri + body;
// 正确的做法
const signStr = method + uri + timestamp + body;
4.3.2 签名算法选错了
不同SDK用的签名算法不一样。有的是HMAC-SHA256,有的是RSA-SHA256,还有的自定义算法。你如果用了HMAC,但服务端配的是RSA,那怎么签都对不上。
我建议:先确认SDK文档里写的是什么算法。然后在代码里显式指定,不要依赖默认值。
| 算法 | 特点 | 常见场景 |
|---|---|---|
| HMAC-SHA256 | 对称签名,密钥不公开 | + Secret做签名 |
| RSA-SHA256 | 非对称签名,私钥签名公钥验证 | OpenAPI、OAuth2 |
| MD5 | 不可逆哈希,不推荐 | 老版本SDK |
4.3.3 时间戳不一致
很多签名算法会把时间戳加入签名字符串,防止重放攻击。但客户端的时钟和服务端的时钟相差太大,签名就对不上。
你可能会问:差多久就失效?这个要看SDK的配置。一般是5分钟。超过这个时间窗口,就算签名算法对,服务器也会拒绝。
我遇到过客户在虚拟机上跑测试,时钟快了整整10分钟。每次请求都报签名失败,改完系统时间就好了。
4.4 总结排查思路
嗯,我们把三种情况排查的先后顺序理一下:
- 先看:有没有填、填没填对、有没有过期。
- 再看:有没有过期、刷新逻辑跑没跑对。
- 最后看签名:参数字段顺序对不对、算法选没选对、时间戳有没有偏差。
这个顺序是我踩坑踩出来的。的问题最快定位,次之,签名最花时间。所以先从快的来。
上面这张图是我在培训新人时经常用的排查流程。从左到右看,先搞定,再搞定,最后搞签名。每步都有对应的报错和解决手段。
最后,做个总结。认证与授权失败,十有八九是这三类问题。先把和的时效性确认好,再去扣签名细节。签名排查时,记得先对齐时间戳,再检查拼接顺序。按照这个思路走,绝大多数问题都能在10分钟内定位出来。