课程0基础Agent开发课 / API入门与模型调用 / API密钥安全管理与环境配置
— 8 min read

API密钥安全管理与环境配置

API 密钥(Key)是访问 LLM 服务的凭证,就像银行卡密码,泄露后果严重:攻击者可以用你的密钥消耗你的配额,产生大量费用,甚至访问你的账户数据。密钥安全管理是 AI 应用工程化的第一道防线。

API 密钥安全管理与环境配置

API 密钥(Key)是访问 LLM 服务的凭证,就像银行卡密码,泄露后果严重:攻击者可以用你的密钥消耗你的配额,产生大量费用,甚至访问你的账户数据。密钥安全管理是 AI 应用工程化的第一道防线。

为什么需要这一篇:新手最常犯的错误是把 API Key 硬编码在代码里,然后提交到 GitHub。GitHub 会自动扫描公开仓库中的密钥并通知,但通知到来时可能已经产生了费用。这篇从根本上解决这个问题。

最常见的错误:密钥硬编码

API密钥安全管理架构图
从环境变量到密钥管理服务的安全访问架构

python
# ❌ 绝对不要这样做
from openai import OpenAI
client = OpenAI(base_url="https://api.deepseek.com", api_key="sk-真实密钥")

# ❌ 不要提交到 git
# 即使是私有仓库,团队成员都能看到,代码泄露时密钥也会泄露

硬编码(即直接把密钥写死在代码文件里,而不是从外部配置读取)的密钥一旦提交到 git(代码版本管理工具,用来追踪代码历史变化,支持多人协作),即使后来删除,在历史记录里仍然存在。GitHub 等平台会扫描公开仓库中的密钥,一旦发现会立即通知,但损失可能已经发生。

基础方案:环境变量

python
import os
from openai import OpenAI

# 从环境变量读取密钥
api_key = os.environ.get("DEEPSEEK_API_KEY")
if not api_key:
    raise ValueError("DEEPSEEK_API_KEY 环境变量未设置")

client = OpenAI(
    base_url="https://api.deepseek.com",
    api_key=api_key
)

在终端设置环境变量(临时,关闭终端后失效):

bash
export DEEPSEEK_API_KEY=sk-你的key
export OPENAI_API_KEY=sk-你的key

开发环境:.env 文件

在项目根目录创建 .env 文件:

bash
# .env
DEEPSEEK_API_KEY=sk-你的key
OPENAI_API_KEY=sk-你的key
DATABASE_URL=postgresql://localhost/mydb
DEBUG=true

关键:把 .env 加入 .gitignore

bash
# .gitignore
.env
.env.local
.env.*.local
*.env

在代码中加载 .env

python
from dotenv import load_dotenv
import os

load_dotenv()  # 加载 .env 文件到环境变量

api_key = os.environ["DEEPSEEK_API_KEY"]

安装 python-dotenv:

bash
pip install python-dotenv
# 或
uv add python-dotenv

不同环境的配置管理

实际项目通常有多个环境:

code
项目根目录/
├── .env              # 本地开发(不提交到 git)
├── .env.example      # 示例文件(提交到 git,不含真实值)
├── .env.test         # 测试环境配置(可能提交,不含密钥)
└── .gitignore        # 确保 .env 不被提交

.env.example 文件(提交到 git,作为文档):

bash
# .env.example - 复制为 .env 并填入真实值
DEEPSEEK_API_KEY=your_deepseek_api_key_here
OPENAI_API_KEY=your_openai_api_key_here
DATABASE_URL=postgresql://localhost/your_db_name
DEBUG=false

加载不同环境的配置:

python
from dotenv import load_dotenv
import os

env = os.environ.get("APP_ENV", "development")

if env == "test":
    load_dotenv(".env.test")
else:
    load_dotenv()  # 默认加载 .env

生产环境:不用 .env 文件

生产服务器上不应该有 .env 文件,密钥应该通过以下方式注入:

Docker/容器部署(Docker 是一种将应用及其依赖打包成"容器"的技术,方便在不同服务器上一致地运行):

bash
# docker run 时传入环境变量
docker run -e DEEPSEEK_API_KEY=xxx -e OPENAI_API_KEY=yyy my-app

# docker-compose.yml
services:
  app:
    environment:
      - DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}  # 从宿主机环境读取

云平台(以常见平台为例)

bash
# Heroku
heroku config:set DEEPSEEK_API_KEY=xxx

# Railway
railway variables set DEEPSEEK_API_KEY=xxx

# Vercel
vercel env add DEEPSEEK_API_KEY

Kubernetes Secret(Kubernetes 是一种容器编排平台,用于管理大规模服务器上的应用程序;Secret 是它存储敏感配置的专用对象):

yaml
apiVersion: v1
kind: Secret
metadata:
  name: api-keys
type: Opaque
data:
  deepseek-api-key: base64编码的密钥

使用 pydantic-settings 管理配置

对于稍复杂的项目,推荐用 pydantic-settings(一个 Python 库,在 pydantic 数据验证功能的基础上专门增强了配置管理能力,能自动从环境变量读取配置并做类型校验)统一管理配置:

python
from pydantic_settings import BaseSettings
from pydantic import SecretStr

class Settings(BaseSettings):
    # SecretStr 类型:打印时会显示 ***** 而不是真实值
    deepseek_api_key: SecretStr
    openai_api_key: SecretStr | None = None

    # 普通配置项
    model: str = "deepseek-chat"
    max_tokens: int = 1024
    debug: bool = False

    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"

# 单例模式
settings = Settings()

# 使用
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.deepseek.com",
    api_key=settings.deepseek_api_key.get_secret_value()
)

pydantic-settings 的优势:

  • 自动从环境变量和 .env 文件读取
  • 类型验证(配置错误时立即报错,而不是运行时才发现)
  • SecretStr 防止密钥被意外打印到日志

密钥轮换

定期更换 API 密钥是安全最佳实践:

  1. 在控制台创建新密钥
  2. 更新所有使用该密钥的服务配置
  3. 验证新密钥可用
  4. 删除旧密钥

对于高安全要求的场景,可以设置密钥过期时间(部分平台支持)。

检测密钥是否泄露

如果怀疑密钥泄露:

  1. 立即撤销:在 API 控制台删除该密钥
  2. 检查用量:查看是否有异常的 API 调用记录
  3. 审查代码:检查密钥是否出现在代码、日志、错误消息中
  4. 扫描 git 历史:使用 git log -p | grep "sk-" 检查是否有密钥提交记录

工具推荐:

  • git-secrets:在 commit 前扫描,阻止密钥提交
  • truffleHog:扫描 git 历史中的密钥
  • GitHub 的 Secret Scanning:自动扫描公开仓库

最小权限原则

如果 API 平台支持,为不同环境创建不同的密钥,并设置最小权限:

  • 开发密钥:低限额,仅用于开发
  • 测试密钥:中等限额,仅用于 CI/CD(持续集成/持续交付,自动化测试和部署代码的流程)
  • 生产密钥:根据业务需求设置限额,定期轮换

这样即使某个环境的密钥泄露,损失也是可控的。


常见错误和解决方法

错误 后果 解决方法
密钥硬编码在代码里 提交到 git 后泄露 改用环境变量或 .env 文件
.env 文件提交到 git 密钥泄露给所有有仓库权限的人 把 .env 加入 .gitignore
所有环境用同一个密钥 一个环境泄露影响全部 按环境创建不同密钥,设置限额
密钥直接写在日志里 日志系统泄露密钥 SecretStr 类型防止打印

小结:密钥安全 checklist

  • 密钥存放在环境变量或 .env 文件中,不在代码里
  • .env 文件已加入 .gitignore
  • 项目提供了 .env.example(不含真实值)
  • 生产环境通过平台环境变量注入,不使用 .env 文件
  • 开发/测试/生产分别使用不同密钥
  • 定期检查 git 历史中是否有密钥泄露(git log -p | grep "sk-"
本页目录