共计 2515 个字符,预计需要花费 7 分钟才能阅读完成。
什么是 API Token?
API Token 就像数字世界的钥匙,它允许你的应用程序安全地访问其他服务或资源。想象一下,每次你想进入家门时不需要每次都输入完整的密码,而是使用一个有时效性的钥匙——这就是 API Token 的基本概念。

常见类型
- JWT (JSON Web Token)
- 自包含的令牌,包含用户信息和签名
- 适用于无状态的身份验证
-
示例:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c -
OAuth Token
- 用于授权第三方应用访问资源
- 包含访问令牌和刷新令牌
-
示例:GitHub API 的 OAuth 流程
-
API Key
- 简单的静态令牌
- 通常用于简单的服务间认证
- 示例:
sk_test_51Hx...(类似 Stripe 的 API Key)
新手常犯的错误
刚开始使用 API Token 时,开发者容易掉入这些陷阱:
- 硬编码 Token:直接把 Token 写在代码里并上传到 GitHub
- 不安全的存储:将 Token 存储在客户端的不安全位置
- 忽略 HTTPS:在不加密的 HTTP 连接中传输敏感 Token
- 过期处理不当:没有正确处理 Token 过期的情况
- 权限过大:给 Token 分配不必要的宽泛权限
安全的 Token 生成示例
Python 示例(使用 JWT)
import jwt
import datetime
from secrets import token_hex
# 生成安全的随机密钥
SECRET_KEY = token_hex(32)
# 创建 JWT Token
def create_jwt_token(user_id):
payload = {
'user_id': user_id,
'exp': datetime.datetime.utcnow() + datetime.timedelta(hours=1), # 1 小时后过期
'iat': datetime.datetime.utcnow()}
return jwt.encode(payload, SECRET_KEY, algorithm='HS256')
# 示例使用
token = create_jwt_token('user123')
print(f"Generated Token: {token}")
Node.js 示例
const jwt = require('jsonwebtoken');
const crypto = require('crypto');
// 生成安全的随机密钥
const SECRET_KEY = crypto.randomBytes(32).toString('hex');
// 创建 JWT Token
function createJwtToken(userId) {
return jwt.sign(
{
userId: userId,
iat: Math.floor(Date.now() / 1000),
// 1 小时后过期
exp: Math.floor(Date.now() / 1000) + (60 * 60)
},
SECRET_KEY,
{algorithm: 'HS256'}
);
}
// 示例使用
const token = createJwtToken('user123');
console.log(`Generated Token: ${token}`);
Token 验证流程
一个完整的 Token 验证应该包含以下步骤:
- 客户端在请求头中发送 Token(通常是 Authorization 头)
- 服务器端提取并验证 Token 签名
- 检查 Token 是否过期
- 验证 Token 中的 claims(如用户角色、权限)
- 如果验证通过,处理请求;否则返回 401 错误
Python 验证示例
def verify_jwt_token(token):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
return payload
except jwt.ExpiredSignatureError:
# Token 已过期
raise Exception('Token expired')
except jwt.InvalidTokenError:
# 无效 Token
raise Exception('Invalid token')
# 示例使用
try:
user_data = verify_jwt_token(token)
print(f"Authenticated user: {user_data['user_id']}")
except Exception as e:
print(f"Authentication failed: {str(e)}")
安全存储方案对比
| 存储位置 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| HttpOnly Cookie | 防 XSS,自动发送 | 易受 CSRF 攻击 | Web 应用 |
| LocalStorage | 易于前端访问 | 易受 XSS 攻击 | SPA 应用 |
| SessionStorage | 标签页关闭即清除 | 不持久 | 临时会话 |
| 内存变量 | 最安全 | 刷新页面即丢失 | 高安全需求 |
HTTPS 的必要性
没有 HTTPS,API Token 就像明信片一样容易被窃取:
- 中间人攻击者可以轻松截获 Token
- Token 可能会被重放使用
- 即使 Token 是加密的,元数据也会泄露
务必 确保:
- 生产环境强制使用 HTTPS
- 设置 HSTS 头
- 定期更新 SSL 证书
生产环境建议
Token 过期策略
- 短期访问 Token:1- 2 小时过期
- 长期刷新 Token:7-30 天过期(存储在安全的 HttpOnly Cookie 中)
- 滑动过期:活跃用户自动延长会话
监控和限流
- 记录所有 Token 验证尝试(成功和失败)
- 对频繁失败的 IP 实施限流
- 监控异常的 Token 使用模式
防爆破措施
- 实现速率限制(如每分钟 5 次尝试)
- 多次失败后临时锁定账户
- 使用 CAPTCHA 验证
延伸思考
- 如何在微服务架构中安全地传递 Token?
- 无状态认证和有状态会话各有什么优缺点?
- 如果发现 Token 被盗,如何快速撤销所有已发放的 Token?
希望通过这篇文章,你能建立起 API Token 安全使用的正确观念和实践方法。记住,安全不是一次性的工作,而是需要持续关注和改进的过程。
正文完
发表至: 未分类
近两天内
