Tutorials

保护环境变量中的 CaptchaAI 凭证

答案很短:CaptchaAI 的 API Key 一律放进环境变量,代码里只留 os.environ["CAPTCHAAI_API_KEY"] 这样的读取语句。下面按“本地开发 → 系统变量 → 容器 → CI/CD → 启动校验”给出每一层的配置。

踩坑的通常不是安全意识,而是协作流程。有人调试时把 Key 写进 config.py,第二天它就同时躺在提交历史、CI 日志和镜像层里。删文件抹不掉这些副本,只能重置 Key。环境变量的价值就在于:密钥的生命周期和代码仓库解耦。


本地开发:.env 文件配合 .gitignore

在项目根目录创建 .env

CAPTCHAAI_API_KEY=your_actual_api_key_here

先写 .gitignore,再写 Key——顺序反了,历史里就多了一次带密钥的提交。

.gitignore 里必须有的几行

# .gitignore
.env
.env.local
.env.production

Python:用 python-dotenv 读取

pip install python-dotenv

国内装依赖慢就加镜像源:pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-dotenv

import os
from dotenv import load_dotenv

load_dotenv()

API_KEY = os.environ["CAPTCHAAI_API_KEY"]

# Use in API calls
import requests
resp = requests.post("https://ocr.captchaai.com/in.php", data={
    "key": API_KEY,
    "method": "userrecaptcha",
    "googlekey": "6Le-SITEKEY",
    "pageurl": "https://example.com",
    "json": "1",
})
print(resp.json())

这里用 os.environ[...] 而非 .get():缺 Key 时立刻抛错,好过带着 None 跑到 in.php。

Node.js:用 dotenv 读取

npm install dotenv
require('dotenv').config();

const API_KEY = process.env.CAPTCHAAI_API_KEY;

if (!API_KEY) {
  console.error('CAPTCHAAI_API_KEY not set');
  process.exit(1);
}

// Use in API calls
const axios = require('axios');
const resp = await axios.post('https://ocr.captchaai.com/in.php', null, {
  params: {
    key: API_KEY,
    method: 'userrecaptcha',
    googlekey: '6Le-SITEKEY',
    pageurl: 'https://example.com',
    json: 1,
  },
});
console.log(resp.data);

Node.js 缺 Key 时不会自动报错,显式判空并 process.exit(1),让问题在启动阶段暴露。


系统级环境变量:不依赖 .env 文件

  • 常驻服务器的任务:直接设系统变量,不必逐台分发 .env
  • cron 与 systemd:不依赖工作目录,重启后照样读得到。

Linux / macOS

export CAPTCHAAI_API_KEY="your_actual_api_key_here"

# Persist across sessions — add to ~/.bashrc or ~/.zshrc
echo 'export CAPTCHAAI_API_KEY="your_actual_api_key_here"' >> ~/.bashrc

Windows(PowerShell)

$env:CAPTCHAAI_API_KEY = "your_actual_api_key_here"

# Persist permanently
[System.Environment]::SetEnvironmentVariable("CAPTCHAAI_API_KEY", "your_actual_api_key_here", "User")

$env: 只对当前会话有效,SetEnvironmentVariable 才持久化,两种写法都写进 README。


容器化部署:Docker 与 Docker Compose

docker run 直接注入

docker run -e CAPTCHAAI_API_KEY="your_key" my-scraper

Docker Compose 引用宿主机变量

# docker-compose.yml
services:
  scraper:
    image: my-scraper
    environment:

      - CAPTCHAAI_API_KEY=${CAPTCHAAI_API_KEY}

${CAPTCHAAI_API_KEY} 引用宿主机变量,密钥不进 compose 文件,这份文件可以放心提交。

Docker Swarm secrets:不走环境变量

环境变量的弱点是 docker inspect 也读得到。Swarm 下改用 secrets,密钥以文件挂载:

echo "your_actual_api_key_here" | docker secret create captchaai_key -
# docker-compose.yml (Swarm mode)
services:
  scraper:
    image: my-scraper
    secrets:

      - captchaai_key
secrets:
  captchaai_key:
    external: true

代码里按普通文件读取:

with open("/run/secrets/captchaai_key") as f:
    API_KEY = f.read().strip()

CI/CD 流水线里的密钥

GitHub Actions

# .github/workflows/scrape.yml
jobs:
  scrape:
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v4
      - run: python scraper.py
        env:
          CAPTCHAAI_API_KEY: ${{ secrets.CAPTCHAAI_API_KEY }}

Settings → Secrets and variables → Actions 添加;Actions 会掩码日志里的 secret。

GitLab CI(含自建实例)

# .gitlab-ci.yml
scrape:
  script:

    - python scraper.py
  variables:
    CAPTCHAAI_API_KEY: $CAPTCHAAI_API_KEY
  • Settings → CI/CD → Variables 添加变量。
  • 勾选 Masked(日志掩码)和 Protected(只对受保护分支下发)。
  • 自建 GitLab 上这两个开关默认关闭,漏勾就是密钥明文进 job 日志。

四个高频翻车点

错误做法 风险 处理方式
.env 提交进 Git 密钥永久留在仓库历史 首次提交前写进 .gitignore
日志里打印完整 API Key 密钥进入日志采集系统 只打印前 4 位,其余掩码
Dockerfile 里用 ENV 写死 Key 密钥固化进镜像层 运行时注入,不写进构建阶段
用微信、邮件传 Key 传输和留存不可控 用密钥管理服务或内部安全通道

启动时先校验 Key,再跑任务

跑了二十分钟才发现 Key 拼错或余额不足,最亏。启动时先确认一次:

import os
import sys
import requests

API_KEY = os.environ.get("CAPTCHAAI_API_KEY")
if not API_KEY:
    print("ERROR: CAPTCHAAI_API_KEY environment variable not set")
    sys.exit(1)

# Verify key works
resp = requests.get("https://ocr.captchaai.com/res.php", params={
    "key": API_KEY, "action": "getbalance", "json": "1"
}).json()

if resp["status"] != 1:
    print(f"ERROR: Invalid API key — {resp['request']}")
    sys.exit(1)

print(f"API key valid — balance: ${float(resp['request']):.2f}")
  • 一次请求确认两件事:变量存在,且 Key 在 CaptchaAI 侧有效。
  • 返回的余额顺手当监控指标,低于阈值即告警。

一个更贴近国内团队的场景

做跨境电商数据的团队,采集的海外站点多是 reCAPTCHA v2 和 Cloudflare Turnstile,内部跑自建 GitLab。合理的分层是:

  • 本地:每人一把测试 Key,放自己的 .env
  • 测试:Key 存 GitLab Group 级变量,勾 Masked,只对受保护分支开放。
  • 生产:容器从 Swarm secrets 或云端密钥管理服务读取,运维之外拿不到明文。

三套环境三把 Key,泄露一把只需重置一把。并发由套餐线程数决定,和 Key 数量无关——BASIC 每月 $15、5 个线程。采集数据时《网络安全法》《数据安全法》和 robots 协议同样适用:只采集你有权采集的数据。


常见问题

一个 .env 文件里可以放多个 API Key 吗?

可以,用逗号分隔即可:

CAPTCHAAI_KEYS=key1,key2,key3
keys = os.environ["CAPTCHAAI_KEYS"].split(",")

多把 Key 解决的是隔离和用量归属,不是并发。

环境变量里的 Key 会不会出现在报错堆栈里?

会。不少框架在未捕获异常时打印完整环境快照。把 CAPTCHAAI_API_KEY 加进敏感字段屏蔽列表,写日志时只输出前 4 位。

镜像里已经用 ENV 写死了 Key,重新构建一次就安全了吗?

不够。旧镜像层还在私有仓库和本地缓存里,docker history 就能看到。正确顺序:先在 CaptchaAI 控制台重置 Key,再改 Dockerfile 重建,最后清理历史镜像标签。


现在就把 Key 从代码里搬出去

captchaai.com 注册拿到 API Key,第一步就写进环境变量。


相关指南

该文章已禁用评论。