微信小程序 / H5 调用第三方 API 的正确姿势:密钥不下前端,请求走自己的服务端
小程序和 H5 直接在前端调用第三方 API,会把密钥暴露在可解包、可查看的代码里。可行做法是前端只请求自己的服务端,由服务端持有密钥、完成鉴权、限流、缓存与错误归一;小程序的可信域名配置、H5 的跨域规则、平台登录态细节需以官方文档为准,本次材料未提供,标为待核实。
如果问“正确姿势”是什么,可以先给一个结论:前端(微信小程序或 H5)不要直接持有第三方 API 的密钥,也不要把第三方域名当成自己的唯一依赖;请求先到自己控制的中间层,再由中间层去调用第三方。小程序与 H5 的差异主要出现在请求域名配置、跨域约束和运行环境能力上,具体规则以官方文档为准——本次材料未提供官方链接,相关细节标为待核实。
为什么不能在前端直接放密钥#
小程序代码包可以被解包查看,H5 的 JavaScript 会被浏览器完整下载。任何写进前端的密钥、签名盐值或长期令牌,都应视为已经公开。以 API.PLUS 这类第三方 API 服务为例,密钥一旦泄露,消耗的是你的额度与配额,而不是攻击者的成本。判断标准很简单:这段字符串是否随构建产物一起发布——是,就不能是密钥。
前端直连还有第二个问题:调用方无法区分“正常用户”和“拿着你的密钥的任何人”。限流、配额、审计都必须放在你能控制的边界上。
推荐的调用链路#
三层即可,不必更复杂:
- 前端:只请求自己的接口路径(如
/api/xxx),携带用户会话凭据,不携带第三方密钥。 - 中间层:校验会话、做参数白名单、限流、缓存,替换成真实密钥后转发。
- 第三方 API:只对中间层的出口 IP 或凭据开放。
这样做的代价是多一次网络往返和一层运维;收益是密钥可轮换、请求可计量、失败可归一。
小程序与 H5 各自要注意什么#
| 关注点 | 微信小程序 | H5 |
|---|---|---|
| 请求域名 | 通常需要在平台侧配置可信请求域名,具体字段与规则待核实 | 受浏览器同源策略约束,跨域需服务端返回 CORS 响应头 |
| 密钥可见性 | 代码包可被解包,不可放密钥 | 源码可被查看,不可放密钥 |
| 会话凭据 | 登录态获取方式待核实 | 一般用 Cookie 或请求头 Token |
跨域是 H5 侧最常见的阻塞点:预检请求(OPTIONS)要放行,Access-Control-Allow-Origin 不要图省事写成通配符再叠加凭据,两者在浏览器侧不兼容。小程序侧的域名配置与本地调试绕过方式,本次材料未提供依据,不展开。
中间层的最小职责示例#
下面是一个结构示意,未执行、未在真实环境验证,仅用于说明层次;接口路径、上游地址与字段名都是占位。
// 未执行的示例:占位代码,未运行
import express from 'express';
const app = express();
const UPSTREAM = process.env.UPSTREAM_BASE; // 占位:由部署环境注入
const KEY = process.env.VENDOR_KEY; // 占位:不入前端包、不入仓库
app.get('/api/weather', async (req, res) => {
const city = String(req.query.city ?? '').slice(0, 32);
if (!city) return res.status(400).json({ error: 'city_required' });
const r = await fetch(`${UPSTREAM}/weather?city=${encodeURIComponent(city)}`, {
headers: { Authorization: `Bearer ${KEY}` },
signal: AbortSignal.timeout(5000),
});
if (!r.ok) {
// 把上游错误归一,不把上游原始报文直接透给前端
return res.status(502).json({ error: 'upstream_failed', status: r.status });
}
res.set('Cache-Control', 'public, max-age=60');
res.json(await r.json());
});
app.listen(3000);
该示例假定运行环境提供全局 fetch 与 AbortSignal.timeout;若不提供,需替换为等价的 HTTP 客户端与超时控制,这一点未验证。
几个容易踩的边界#
- 错误码不要透传。上游的 401/429 直接给前端,会让前端误以为是自己的登录失效。中间层应映射成自己的一套错误语义。
- 重试要看幂等性。GET 类查询可以有限重试,写操作不要盲目重放,否则可能重复计费或重复下单。
- 缓存是省钱手段,也是正确性问题。缓存键要包含所有影响结果的参数(如城市、语言、单位),否则会串数据。
- 限流放在中间层。按用户维度限流,而不是按 IP 一刀切。
- 密钥轮换要有预案。密钥从环境变量注入,改配置即可替换,不要写进代码后靠重新发版。
写作说明:本次没有可用的正文素材与官方文档链接,文中关于平台配置项、登录态、配额与计费的具体规则均未核实,涉及实际接入时应以官方文档为准;文中代码为结构示意,未执行。