资讯文章 资讯 · NEWS
第三方登录那串 client_secret 放哪:目录站的 OAuth 客户端该怎么管
2026-10-24 约 1,390 字 预计阅读 3 分钟 yiyunkj
第
目录站既是客户端(让用户用微信、GitHub 登录),也可能当服务端(给别人开放接口)。这两件事的风险点不一样,但都绕不开同一组配置:客户端标识、密钥、回调地址、授权范围。
2025 年 1 月发布的 RFC 9700 把过去十年踩过的坑整理成了正式的最佳实践,里面有几条直接推翻了不少团队沿用了好几年的写法。

图片来源:网络,版权归原作者所有,侵权请联系删除
回调地址要精确匹配,通配符已经是过去式
授权码是通过浏览器重定向带回来的,谁控制了回调地址,谁就能拿到码。RFC 9700 的要求很硬:授权服务器必须对 redirect_uri 做精确字符串匹配,唯一的例外是本机应用的环回地址端口可以变动(这一条来自 RFC 8252)。
现实里最常见的松动是三种:主机位置放通配符、路径按前缀匹配、测试和生产共用一个宽松地址。前两种会让攻击者注册的子域变成合法落地页,第三种等于把生产环境的授权码开放给了任何能猜到测试地址的人。
还有一类更隐蔽:回调页自己带了个 next 或 return_to 参数,登录完跳到参数指定的地址。精确匹配挡不住这种开放重定向,得在回调页里把目标地址限定在自己的路径白名单内。域名停用时也要记得去服务商那里注销回调地址——一个指向空的子域,别人是可以抢注的。
PKCE 不只给移动端用
PKCE(RFC 7636)最初是为原生应用设计的,因为原生应用藏不住密钥。它的机制是客户端先生成一串随机验证码,把哈希值随授权请求发出去,换令牌时再出示原始值,服务端两边对不上就拒绝。
关键点在于:它能挡住的是授权码被截获后被冒用,而这事在 Web 应用上同样会发生。所以 RFC 9700 的建议是授权码流程一律配 PKCE,包括有密钥的机密客户端。同时它明确把隐式流和密码模式标记为不推荐使用,还在跑的项目该排期迁走了。
| 配置项 | 常见做法 | 该改成什么 |
|---|---|---|
| 回调地址 | 配一个通配或前缀 | 按环境逐个注册,精确匹配 |
| PKCE | 只有移动端开 | 所有授权码流程都开 |
| 授权范围 | 一次把能要的都要了 | 按当前功能要,缺了再申请 |
| state 参数 | 省了,反正有 session | 必带,回来校验,防跨站请求 |
| 刷新令牌 | 长期不换,存一个字段 | 每次使用轮换,或做发送方约束 |
密钥的存放和轮换
client_secret 是一串长期有效的凭据,它的风险等级和数据库密码是一档的。三条底线:不进代码仓库(放环境变量或密钥管理服务,仓库里只放示例文件和读取方式);按环境分开申请,测试环境泄露不至于波及生产;日志里不能出现它,调试打印整个请求对象的习惯要改。
轮换是最容易翻车的环节。直接把旧密钥删掉,正在飞行中的请求会全部失败。正确做法是新旧并存一个窗口期:先在服务端部署新密钥并同时接受两者,等确认没有请求再用旧密钥了(看访问日志里密钥标识的分布),再去服务商后台吊销旧的。窗口期给一到两天足够。
如果服务商支持,优先用证书或托管身份认证替代长期密钥,签名的私钥不出机器,比一串共享秘密难泄露得多。
当服务端时多两件事
目录站若对外开放接口,角色就换成了授权服务器那一侧。这时候要额外做两件客户端视角看不到的事:一是校验令牌的颁发者和受众,别拿到一个令牌就用;二是给接口调用方发的是按用途分开的凭据,只读的给只读密钥,能写条目的给另一套,密钥泄露时的止损范围立刻小一个量级。
这几条里没有一条需要额外的预算,全是配置层面的纪律。真正贵的是事后:一个通配回调配了三年,谁也说不清有多少个地址在用,改的时候只能硬切。