进阶 12分钟 3 步骤
API Key安全管理最佳实践
学习如何安全地管理和存储API Key,避免密钥泄露导致的安全风险和财产损失。
#安全
#最佳实践
#密钥管理
#前端安全
前置条件
- 了解 API 的基本概念
- JavaScript/Node.js 基础
概述
为什么API Key安全很重要?
API Key 是访问 API 服务的凭证,一旦泄露可能导致:
- 财产损失:付费API被恶意使用,产生巨额账单
- 数据泄露:敏感数据被非法访问
- 服务滥用:API配额被耗尽,影响正常业务
- 法律风险:被用于非法用途
常见的安全错误
在代码中硬编码 API Key 是最危险的做法。以下是一些应该避免的错误:
- 硬编码在前端代码:任何人可以在浏览器中查看源码
- 提交到 GitHub:密钥会被永久记录在历史记录中
- 写在注释里:开发者疏忽导致泄露
- 硬编码在 App 中:反编译可以直接获取密钥
操作步骤
1
第一步:使用环境变量
永远不要把 API Key 写在代码里,使用环境变量来存储。
bash
# .env 文件(不要提交到版本控制)
API_KEY=your_api_key_here
DATABASE_URL=postgres://...
# .gitignore 添加
.env
.env.local
.env.production
javascript
// 读取环境变量
// Node.js
const apiKey = process.env.API_KEY;
// 前端项目使用 .env 文件
// VITE_API_KEY=xxx
const apiKey = import.meta.env.VITE_API_KEY;
// 安全使用示例
async function callApi() {
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API Key 未配置');
}
const response = await fetch('https://api.example.com/data', {
headers: {
'Authorization': `Bearer ${apiKey}`
}
});
return response.json();
}
提示
- 创建 .env.example 文件作为模板,但不包含实际密钥
- 在 CI/CD 中配置环境变量
- 定期轮换 API Key
2
第二步:后端代理模式
前端永远不应该直接调用需要 API Key 的服务,应该通过自己的后端服务器转发。
javascript
// 后端(Node.js/Express)
const express = require('express');
const axios = require('axios');
const app = express();
// 你的 API Key 只在这里存在
const API_KEY = process.env.API_KEY;
app.get('/api/weather', async (req, res) => {
try {
// 后端使用 API Key 调用外部服务
const response = await axios.get('https://api.weather.com/v1/forecast', {
params: req.query,
headers: {
'X-API-Key': API_KEY
}
});
// 返回处理后的数据给前端
res.json(response.data);
} catch (error) {
res.status(500).json({ error: '获取天气失败' });
}
});
app.listen(3000);
// 前端(只需要调用自己的后端)
// fetch('/api/weather?lat=39.9&lon=116.4')
// 不需要暴露任何 API Key
提示
- 后端可以添加缓存、限流、日志等额外功能
- 前端只调用自己信任的域名
- 后端可以隐藏具体使用的第三方 API
3
第三步:前端安全措施
即使使用后端代理,前端代码也需要注意安全问题。
javascript
// 1. 使用 CSP(内容安全策略)
// 在服务器的 HTTP 头中配置
// Content-Security-Policy: default-src 'self'; script-src 'self'
// 2. 防止 XSS 攻击
function safeRender(data) {
// 使用 textContent 而不是 innerHTML
document.getElementById('output').textContent = data;
}
// 3. 使用 HttpOnly Cookie 存储敏感信息
// 服务器设置
// res.cookie('session', sessionId, { httpOnly: true, secure: true });
// 4. 验证请求来源
app.use((req, res, next) => {
const allowedOrigins = ['https://yourdomain.com'];
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access-Control-Allow-Origin', origin);
}
next();
});
// 5. 添加请求速率限制
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100 // 最多100个请求
});
app.use('/api/', limiter);
提示
- 永远不要在 localStorage 中存储敏感信息
- 使用 HTTPS 确保传输安全
- 添加 CSRF Token 防止跨站请求伪造
常见错误与解决方案
API Key 泄露了
立即在 API 提供商后台禁用该密钥,生成新的。检查使用记录,确认是否有异常消费。
前端代码中不小心暴露了 Key
删除 Git 历史记录中的 Key,重新生成新的 Key,更新所有环境配置。
第三方 SDK 在前端暴露了 Key
使用后端代理所有需要认证的请求,确保 Key 只存在于后端。