Python如何安全地生成随机密码或Token_使用secrets模块替代random
生成密码或Token应使用secrets模块而非random模块,因为random依赖伪随机数生成器,种子可预测、输出可重现,不具备密码学安全性,易被破解。secrets基于系统安全熵,提供token_urlsafe()生成URL友好Token、choice()定制密码及compare_digest()防止时序攻击,从而确保安全可靠。
为什么不能用 random 生成密码或 Token
`random` 模块用的是伪随机数生成器(PRNG),种子可预测、输出可重现,不适合安全场景。比如用 `random.choice()` 生成的 API Token,如果攻击者知道程序启动时间或部分输出,就可能反推后续所有值。
从底层看:
- `random` 不保证密码学安全性,哪怕调用了 `SystemRandom`,其底层仍依赖 OS 的非加密随机源(如 `/dev/urandom`)——但 `random` 自己没做熵校验和重采样。
- Python 3.6+ 明确推荐用 `secrets` 替代 `random` 做安全敏感操作。
- Web 框架(如 Flask、FastAPI)的 `secret_key` 或 `session_id` 生成逻辑,若手动拼接 `random` 结果,会直接降低整体安全性。
用 secrets.token_urlsafe() 生成 URL 友好 Token
这是最常用也最省心的方式:生成 Base64Url 编码字符串,不含 `+`、`/`、`=`,能直接放进 URL、HTTP Header 或数据库字段。
要注意的是,长度参数是「字节长度」,不是最终字符串长度。Base64Url 编码后长度 ≈ ⌈(n × 4)/3⌉,所以要 32 字符 Token,传 `24` 字节更准:
```python
import secrets
token = secrets.token_urlsafe(24) # 实际生成约 32 个字符
# 示例输出: 'xvL9aKmQ2rFzB4tN7wYpE8sJ'
```
关键要点:
- 默认使用 `/dev/urandom`(Linux/macOS)或 `CryptGenRandom`(Windows),系统级密码学安全随机源。
- 不建议用 `secrets.token_urlsafe(16)` 生成密码——它只提供约 128 位熵,对长期口令不够;密码应至少 16 字节(128 bit)以上。
- 避免在循环里反复调用生成多个 token 后拼接,这不会增加熵,反而可能引入时序侧信道。
用 secrets.choice() + 字符集定制密码
如果需要控制字符类型(比如必须含大小写字母、数字、符号),用 `secrets.choice()` 安全地从自定义字符集中抽样。别用 `random.choice()`,哪怕加了 `SystemRandom` 也不行。
```python
import secrets
import string
alphabet = string.ascii_letters + string.digits + "!@#$%&*"
password = ''.join(secrets.choice(alphabet) for _ in range(16))
```
几个容易忽略的细节:
- 字符集别漏掉引号里的转义字符,比如 `\!@\#$\%` 直接写成 `!@#$%` 就行,Python 字符串本身不解释这些。
- 不要用 `secrets.randbelow(len(alphabet))` 再索引——虽然也安全,但比 `secrets.choice()` 多一次计算,且易写错边界(如 `randbelow(len(alphabet)-1)`)。
- 如果要求“至少一个大写、一个小写、一个数字”,得用拒绝采样法重试,不能靠概率估算后固定位置插入——否则会降低熵值。
secrets.compare_digest() 防止时序攻击
生成完密码或 token 后,校验时别用 `==` 直接比较字符串。攻击者可通过响应时间差异推测出前缀是否匹配。
`secrets.compare_digest()` 是恒定时间比较函数,无论输入是否相等,执行时间都一致:
```python
if secrets.compare_digest(user_input_token, stored_token):
grant_access()
else:
deny_access()
```
几点提醒:
- 仅适用于 bytes 或 str 类型,且两个参数类型必须一致(不能 str vs bytes)。
- Django 和 Flask 的 session 签名验证底层已用类似机制,但你自己写的 token 校验点必须手动加。
- 别试图自己实现恒定时间比较——容易写出被编译器优化掉的“假恒定时间”代码。
真正难的不是选对函数,而是意识到哪些地方需要它:Token 生成只是起点,存储加密、传输 HTTPS、校验方式、过期策略、错误提示粒度……每个环节松动一环,前面用 `secrets` 做的就白费了。

Postman是一套面向API全生命周期的开发与测试平台,可在Mac上发送和调试多种协议请求,管理集合、环境及认证信息,并完成脚本测试、模拟服务、监控、文档发布和团队协作。它适合开发、测试及运维人员使用,提供个人免费方案。
Docker Desktop 是 Docker 官方为 Mac 提供的容器开发环境,集成 Docker Engine、命令行工具、Compose、Build、Kubernetes 与图形化管理界面。
Android Studio 是 Google 面向安卓应用开发提供的官方集成开发环境,基于 IntelliJ IDEA 构建。它整合智能代码编辑、Gradle 构建、界面预览、设备模拟、性能分析、调试测试及 APK 分析等工具。
PixPix 是面向品牌、卖家和内容团队的在线 AI 图片视频创作平台,提供图视频 Agent、无限画布、图片生成、视频生成、自然语言编辑及商品套图、产品精修和带货视频等电商工具。
Postman 是面向 API 全生命周期的开发与协作平台。Windows 桌面版可用于构建和发送 HTTP、GraphQL、gRPC、WebSocket、MQTT 等请求,并提供环境变量、集合、脚本测试、模拟服务、监控、文档及团队工作区等
Docker Desktop 为 Windows 开发者提供集成式容器环境,内置 Docker Engine、命令行工具、Compose、Build 与 Kubernetes 等组件,可在本机完成镜像构建、容器运行、日志查看和资源管理。













