3. 认证授权错误(上):401 Unauthorized
说实话,在SDK接入的各类报错里,401 Unauthorized 是出场率最高的选手之一。你可能刚配好环境,一调接口就撞上它。我记得刚带团队那会儿,有个同事盯着一堆401抓狂了三小时,最后发现是首字母多了个不可见字符。嗯,这种坑我踩过不少,今天咱就把这层纸捅破。
3.1 401 到底在说什么?
从HTTP层面讲,401就是「你没有有效的身份凭证」。说白了,服务端认不出你是谁,或者不信任你交出来的凭证。但它跟403不一样:403是「我知道你是谁,但你不配干这事」。这个后面会细说。
关键区分:
- 401 → 认证(Authentication)失败 → 你是谁?
- 403 → 授权(Authorization)不足 → 你能干啥?
我碰到过不少开发者把这两个混着调,结果越修越乱。记得有一次,明明是好的,服务端报了401,最后发现是请求Header里把 Authorization 拼成了 Authorization(少了个i)。这种低级错误,排查起来最磨人。
3.2 过期与刷新机制
现在的SDK认证,主流方案都走。最常见的就是 JWT(JSON Web )。我自己习惯把理解成一个「临时身份证」——它有有效期,到了点就作废。
3.2.1 为什么设计成短时效?
你想想看,如果永久有效,一旦泄露就等于把账户拱手送人。所以服务端通常把access 的有效期设为15分钟到2小时。我见过一些电商平台的SDK,有效期只有30分钟,安全策略非常严格。
3.2.2 刷新流程:我踩过的坑
| 概念 | 说明 | 有效期示例 |
|---|---|---|
| Access | 用于接口请求的凭证 | 15分钟 - 2小时 |
| Refresh | 用于换取新的 Access | 7天 - 30天 |
| Client ID / Secret | 应用级凭证,用于初次获取 | 长期有效(视平台) |
曾经有个项目,我们只处理了Access 过期的情况,却忘了Refresh 也可能过期。结果用户月初正常,月中突然全部401——Refresh 过期了,SDK没有走重新登录的兜底逻辑。那次线上事故教训很深。
3.2.3 标准的刷新流程
- 用 Access 请求接口,收到 401。
- 判断是否为「凭证过期」类错误码(比如 40101)。
- 用 Refresh 调用刷新接口,拿到新的 Access 。
- 用新 重试原来的请求。
- 如果 Refresh 也过期 → 清除本地凭证,引导用户重新登录。
// 伪代码举例:刷新逻辑
async function refreshAccessToken(refreshToken) {
try {
const response = await fetch('/auth/refresh', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ refreshToken: refreshToken })
});
if (!response.ok) {
// 走到这里,Refresh 可能也废了
throw new Error('Refresh expired');
}
const data = await response.json();
// 更新本地存储的
localStorage.setItem('accessToken', data.accessToken);
localStorage.setItem('refreshToken', data.refreshToken);
return data.accessToken;
} catch (error) {
// 清理凭证,跳转登录页
clearCredentials();
redirectToLogin();
}
}
我的小技巧: 我会在SDK层做一个「请求队列」——当一个请求遇到401时,先暂停其他并发请求,等刷新成功后再统一重试。这样可以避免多个请求同时触发刷新导致冲突。
3.3 管理
虽然是主流,但很多开放平台还是会提供作为简易认证。这东西,说白了就是个静态密码,风险更高。我看过一些接入方直接把写在客户端代码里的,那种情况基本等于把家钥匙挂在大门上。
3.3.1 的最佳实践
- 不要硬编码: 代码仓库里绝不能出现明文。我习惯用环境变量注入。
- 区分环境: 开发、测试、生产用不同的Key。万一泄露可以只禁用某个环境。
- 定期轮换: 我建议至少每90天换一次Key。有些平台提供了双Key机制——新旧Key共存一段时间,方便灰度切换。
- 访问控制: 限制Key能调用的接口范围。比如只允许读,不允许写。
// 环境变量方式注入 (推荐)
const = process.env. || '';
// 错误示范:直接写死
const = 'sk-1234567890abcdef'; // 千万别这么干
严重警告: 如果你发现自己SDK的泄露了,第一时间要做什么?不是改代码——是去后台撤销旧Key并生成新Key,同时检查近期调用记录有没有异常。我曾经帮一个客户排查流量异常,发现有人拿他泄露的Key爬了一个月的付费数据。
3.4 知识结构总览
下面这张图把本章核心逻辑串起来了,你自己看看就更清楚了。
3.5 实战排查清单
如果你正在被401折磨,按这个顺序走一遍,八成能解决:
- 第一步: 检查请求头里的
Authorization字段拼写和格式。大小写、冒号、空格,一个都不能错。我在项目中遇到过客户把Bearer写成了bearer,结果调了半天的梗。 - 第二步: 查看解码后的payload,确认
exp(过期时间)没有小于当前时间。 - 第三步: 如果用了,确认Key没有被撤销,也没有达到调用次数上限。
- 第四步: 检查SDK版本——有些旧版SDK不支持新的认证协议。我记得有一家支付平台升级了签名算法,老版本SDK全崩。
个人习惯: 我会在SDK初始化时主动调用一个「验证凭证」接口。与其等到业务请求突然崩,不如早点死个明白。