AI应用密钥防泄露:环境变量与权限清单

一把泄露的 OpenAI Key,一晚上能刷掉几个月工资。这类事故几乎全部源于同一个习惯:把密钥写死在代码里。这篇按"存放—传输—使用—兜底"四段把防线讲清,最后给一张可勾选的上线清单。

第一道防线:密钥只活在环境变量里

硬编码密钥等于把银行卡密码贴在门口。正确姿势是把敏感配置放进 .env / .env.local,并用 .gitignore 挡住:

# .gitignore
.env
.env.local
.env.*
// 错误:const apiKey = 'sk-xxx'
// 正确:
const apiKey = process.env.OPENAI_API_KEY;

Next.js 有个专门的前后端分界规则要记住:NEXT_PUBLIC_ 前缀的变量会被打进前端包,等于公开;真正的密钥一律不带前缀,只在服务端读。部署到 Vercel 这类平台时,还要在控制台配一份同名变量——本地 .env 不会跟着代码走。

第二道防线:浏览器端不存敏感数据

localStorage 会被页面上任何一段 JS 读取,XSS 一旦得手就是一锅端。密码、完整用户资料、支付信息,一个都不能放。临时数据用 sessionStorage 或 HttpOnly Cookie:

res.setHeader('Set-Cookie',
  'token=xxx; HttpOnly; Secure; SameSite=Strict; Path=/');

HttpOnly 让 JS 读不到,Secure 强制 HTTPS,SameSite=Strict 压掉 CSRF——三个标志缺一不可。

第三道防线:数据库行级安全

Supabase 这类 BaaS 的默认表权限是"知道地址就能读",必须手动开 RLS:

ALTER TABLE your_table ENABLE ROW LEVEL SECURITY;

CREATE POLICY "User can access own data"
ON your_table FOR SELECT USING (auth.uid() = user_id);

没有 RLS 的 Supabase 项目,等于把数据库连接串贴在公网上。

兜底:额度上限是最后的保险丝

前两道防线的目标是"不泄露",但工程上必须假设会泄露。给每个 API Key 配置用量上限,盗刷损失就从"无限"变成"封顶"。原文没有展开的一条增量实践:主 Key 和业务 Key 要分离——前端代理用低额度 Key,后台批处理用高额度 Key,泄露时的爆炸半径完全不同。此外,密钥轮换要有流程:发现泄露后第一步是立刻在平台后台作废重发,而不是先去 Git 历史里删记录(那已经晚了)。

上线前逐项自查

检查项 判定
代码与提交历史里搜不到 sk- 前缀 git log -p \| grep sk-
.env 系列文件全部被 gitignore 且未进远端 git ls-files \| grep .env 为空
Vercel/平台控制台变量与本地一致 部署后接口正常
Supabase 全部表开启 RLS 匿名请求返回空集
浏览器存储无密钥/密码/支付字段 DevTools Application 面板核对
每个 Key 都设了额度上限 平台用量页确认

七项全绿才允许上线。安全这件事没有"差不多"——密钥一旦进过 Git 历史,唯一的正确动作就是作废重发。

0

评论0

请先
显示验证码
没有账号?注册  忘记密码?