在 Python 项目中,绝对禁止将 API Key 硬编码(直接写死)在源代码中。为了保障安全,通常有以下几种推荐的存储方式:
一、 使用环境变量(推荐)
这是最安全且最灵活的方式,特别适合大型项目或使用了 Flask 等框架的场景。它可以将凭证与应用程序代码彻底分离,确保在不同系统上使用不同凭证运行。
操作步骤:
安装依赖: 运行 pip install python-dotenv 安装 python-dotenv 库。
创建配置文件: 在项目根目录创建一个 .env 文件,将密钥写入其中(例如 API_KEY=你的密钥)。
读取变量: 在 Python 代码中加载并读取该环境变量。
python
编辑
from dotenv import load_dotenv
import os
# 加载 .env 文件
load_dotenv()
# 获取 API 密钥
api_key = os.getenv("API_KEY")
注意:务必将 .env 文件添加到 .gitignore 中,防止其被意外提交到 GitHub 等代码仓库。
二、使用独立配置文件
对于较小的项目,可以将敏感数据提取到一个单独的 Python 文件(如 creds.py)中,然后在主代码中通过 import creds 的方式访问变量。
操作步骤:
创建 creds.py 文件,写入 api_key = "你的密钥"。
在主代码中通过 creds.api_key 进行调用。
关键一步: 必须将 creds.py 添加到 .gitignore 文件中,确保该文件不会被上传到代码仓库。
三、系统级环境变量
如果不使用 .env 文件,也可以直接在操作系统中设置环境变量。
Linux/Mac: 使用 export API_KEY=你的密钥。
Windows CMD: 使用 set API_KEY=你的密钥。
然后在 Python 代码中同样使用 os.environ.get("API_KEY") 来获取。
四、使用 Secrets Manager(如 AWS Secrets Manager)
Secrets Manager(如 AWS Secrets Manager)是生产级别应用中存储 API Key 的最佳实践。它不仅能提供最高级别的安全性,还能实现密钥的自动轮换(Rotation),从而彻底消除硬编码带来的安全隐患。
以下是使用 Secrets Manager 安全存储和调用 API Key 的完整方案:
1. 核心优势
消除硬编码: 将 API Key 从代码中完全剥离,避免密钥泄露到日志、PR(Pull Request)或版本控制系统中。
自动轮换(Rotation): Secrets Manager 可以定期自动更新密钥,吊销旧凭证,极大降低安全风险。
细粒度权限控制: 只有被授权的服务器或容器才能获取密钥,实现严格的访问控制。
2. Python 代码实现方案(以 AWS 为例)
在 Python 应用程序中,可以通过 boto3 库安全地获取密钥。建议通过 IAM 角色授权,而不是在代码中写入访问凭证。
python
编辑
import boto3
import os
def get_api_key(secret_id, region_name='us-east-1'):
# 初始化 Secrets Manager 客户端
client = boto3.client('secretsmanager', region_name=region_name)
try:
# 获取密钥值
response = client.get_secret_value(SecretId=secret_id)
api_key = response['SecretString']
return api_key
except Exception as e:
# 密钥获取失败时的异常处理
raise ValueError(f"无法获取密钥 {secret_id}: {str(e)}")
# 使用示例
if __name__ == "__main__":
# 确保在运行环境中配置了正确的 IAM 权限
my_api_key = get_api_key('prod/my-app/api-key')
print("成功获取密钥,开始调用业务逻辑...")
3. 容器化环境(如 Devin AI)的安全集成
如果你在使用类似 Devin AI 的自动化容器环境,严禁在任务指令中直接拼接 URL 或明文传递密钥(这会导致密钥不可逆地暴露在协作链路中)。
正确的做法:
预注入环境变量: 在容器初始化脚本(如 entrypoint.sh)中,通过命令行从 Secrets Manager 拉取密钥并导出为环境变量:
bash
编辑
export MY_API_KEY=$(aws secretsmanager get-secret-value \
--secret-id prod/my-app/api-key \
--query SecretString --output text)
在 Python 脚本中读取: 让 Devin 或自动化任务生成独立的 Python 脚本,通过 os.getenv("MY_API_KEY") 获取密钥。
添加校验逻辑: 在任务脚本开头添加校验,防止因密钥缺失导致无效重试或触发 API 限频熔断:
python
编辑
if not os.getenv("MY_API_KEY"):
raise ValueError("Missing MY_API_KEY in environment")
4. 最佳实践建议
缓存密钥以提升性能: 每次调用 API 都去请求 Secrets Manager 会增加延迟和成本。建议在应用启动时获取一次并缓存在内存中。
使用临时内存: 如果是在本地执行脚本(如 SSH 通信),获取到的私钥应保存在易失性内存(Volatile memory)中,认证完成后立即从内存中覆写并删除,不要写入本地文件系统。
配置自动轮换: 在控制台启用 Automatic rotation,并配置 Lambda 函数来定期更新密钥和数据库/服务端的凭证。
代码审查: 可以使用如 Amazon CodeGuru Reviewer 等工具,自动扫描 Java 和 Python 代码中是否意外残留了硬编码的机密信息。
总结建议:
无论采用哪种方式,核心原则都是代码与密钥分离。对于初学者或小型项目,独立配置文件(配合 .gitignore)实现起来最简单;而对于生产环境或大型项目,强烈建议使用环境变量方案,这不仅安全性更高,也便于后续在不同服务器上进行部署和复制