3. requests 库安全特性:HTTPS 支持、证书验证机制、安全头处理

在供应链安全与权限审计场景中,requests 库的传输层安全特性是镜像源通信的第一道防线。本章聚焦 HTTPS 协议支持、证书链验证机制以及安全响应头处理,帮助 DevSecOps 工程师在自动化巡检中避免中间人攻击、证书劫持与敏感信息泄露。

3.1 HTTPS 支持与协议协商

requests 库默认对 https:// 开头的 URL 启用 TLS 加密传输,底层依赖 urllib3 与 ssl 模块。在镜像源巡检场景中,必须确认服务端支持 TLS 1.2 及以上协议,并禁用已废弃的 SSLv2/v3 与 TLS 1.0/1.1。

协议版本 requests 默认支持 安全水位要求 审计建议
SSLv2 / SSLv3 否(已移除) 禁止 直接阻断
TLS 1.0 / 1.1 是(urllib3 兼容) 禁止 通过 ssl_context 限制
TLS 1.2 是 最低要求 强制启用
TLS 1.3 是(Python 3.7+) 推荐 优先协商
巡检水位指标: 在镜像源证书审计脚本中,应使用 requests.get(..., timeout=10) 并捕获 requests.exceptions.SSLError,同时记录服务端 TLS 版本号,低于 1.2 的节点标记为高危。
import requests
from requests.packages.urllib3.util.ssl_ import create_urllib3_context

# 强制限制 TLS 版本为 1.2+
ctx = create_urllib3_context()
ctx.minimum_version = ssl.TLSVersion.TLSv1_2

session = requests.Session()
session.adapters['https://'].init_poolmanager(ssl_context=ctx)

try:
    resp = session.get('https://mirror.example.com/pypi/simple/', timeout=10)
    print(f"TLS 协商成功,状态码: {resp.status_code}")
except requests.exceptions.SSLError as e:
    print(f"TLS 版本不满足安全水位: {e}")

3.2 证书验证机制

requests 库默认启用证书验证(verify=True),通过系统 CA 包或自定义 CA 文件校验服务端证书链。在供应链镜像源场景中,证书验证失败必须阻断请求,避免中间人攻击。

安全红线: 生产环境禁止设置 verify=False。仅在隔离测试网络中使用自定义 CA 时,可通过 verify='/path/to/ca-bundle.crt' 指定信任锚点。

证书验证的核心流程包括:

  • 证书链构建: 从服务端证书逐级向上验证至根 CA。
  • 主机名校验: 检查证书 CN 或 SAN 是否匹配请求域名。
  • 有效期检查: 确认证书未过期且未生效。
  • 吊销状态: 可选检查 CRL 或 OCSP(requests 默认不内置,需扩展)。
requests 证书验证流程 requests 客户端 镜像源服务器 HTTPS 请求 + 服务端证书 证书链验证(verify=True) ① 解析服务端证书 → ② 构建证书链(中间 CA → 根 CA) ③ 主机名校验(CN / SAN) → ④ 有效期检查 → ⑤ 信任锚点匹配 验证通过 ✓ 验证失败 ✗ 正常响应数据 抛出 SSLError

3.3 安全响应头处理

镜像源 HTTP 响应中携带的安全头直接影响供应链审计水位。requests 库本身不自动处理安全头,但 DevSecOps 巡检脚本必须检查以下关键头字段:

安全头名称 作用 审计水位要求 requests 检查方式
Strict-Transport-Security 强制后续请求使用 HTTPS 必须存在,max-age ≥ 31536000 resp.headers.get('Strict-Transport-Security')
Content-Security-Policy 限制资源加载来源 建议存在,至少包含 default-src 'self' resp.headers.get('Content-Security-Policy')
X-Content-Type-Options 禁止 MIME 嗅探 必须为 nosniff resp.headers.get('X-Content-Type-Options')
X-Frame-Options 防止点击劫持 建议为 DENY 或 SAMEORIGIN resp.headers.get('X-Frame-Options')
Cache-Control 控制缓存策略,防止敏感数据缓存 建议包含 no-store resp.headers.get('Cache-Control')
巡检脚本示例: 以下代码片段用于审计镜像源响应安全头,缺失或不符合水位要求的头将被记录到审计日志。
import requests

SECURITY_HEADERS = {
    'Strict-Transport-Security': lambda v: v and 'max-age=31536000' in v,
    'X-Content-Type-Options': lambda v: v == 'nosniff',
    'Content-Security-Policy': lambda v: v is not None,
    'X-Frame-Options': lambda v: v in ('DENY', 'SAMEORIGIN'),
}

def audit_security_headers(url):
    try:
        resp = requests.get(url, timeout=10, verify=True)
        audit_results = {}
        for header, check_fn in SECURITY_HEADERS.items():
            value = resp.headers.get(header)
            passed = check_fn(value)
            audit_results[header] = {
                'present': value is not None,
                'value': value,
                'passed': passed
            }
        return audit_results
    except requests.exceptions.RequestException as e:
        return {'error': str(e)}

# 审计示例
result = audit_security_headers('https://pypi.org/simple/')
for header, info in result.items():
    status = '✅' if info.get('passed') else '❌'
    print(f"{status} {header}: {info.get('value', '缺失')}")

3.4 证书固定与自定义信任策略

在内部镜像源或私有 PyPI 场景中,可能需要使用自签名证书或企业 CA。requests 支持通过 verify 参数指定自定义 CA 包,也支持通过 cert 参数提供客户端证书用于双向 TLS 认证。

import requests

# 场景一:使用自定义 CA 包验证服务端
resp = requests.get(
    'https://internal-mirror.company.com/simple/',
    verify='/etc/ssl/certs/company-ca.crt',
    timeout=10
)

# 场景二:双向 TLS(mTLS)客户端证书
resp = requests.get(
    'https://secure-mirror.company.com/simple/',
    cert=('/path/to/client.crt', '/path/to/client.key'),
    verify='/etc/ssl/certs/company-ca.crt',
    timeout=10
)
权限审计要点: 在供应链巡检中,证书文件(.crt、.key)的读取权限必须严格限制。巡检脚本应检查证书文件权限是否为 600 或 400,避免私钥泄露。

3.5 安全水位巡检清单

综合以上内容,针对 requests 库的 HTTPS 与证书安全巡检,建议按以下清单逐项检查:

  1. 协议版本: 确认服务端 TLS 版本 ≥ 1.2,拒绝旧版协议。
  2. 证书验证: 确保 verify=True,未使用 verify=False 的豁免配置。
  3. 证书链完整性: 检查证书链是否完整,根 CA 是否在信任库中。
  4. 主机名校验: 确认证书 CN/SAN 匹配请求域名。
  5. 安全响应头: 至少检查 HSTS、X-Content-Type-Options、CSP 三个头。
  6. 证书文件权限: 自定义 CA 或客户端证书文件权限不超过 600。
  7. 会话复用: 使用 requests.Session() 时注意连接池的 TLS 上下文一致性。
自动化集成: 将上述巡检清单封装为 check_requests_tls_watermark() 函数,集成到 CI/CD 流水线中,每次镜像源同步前自动执行水位检查,不达标则阻断发布。