Skip to content

第 8 章 · 代理与 SSL/TLS

本章目标:掌握通过代理访问网络、SSL 证书验证与客户端证书配置,确保请求安全可控。

8.1 为什么需要代理

代理(Proxy)在企业网络中极为常见:防火墙要求所有出站流量经过代理、使用代理访问被屏蔽的资源、或者需要通过代理进行流量监控。

python
import requests

# 设置 HTTP 代理
proxies = {
    'http': 'http://10.10.1.10:3128',
    'https': 'http://10.10.1.10:3128',
}

resp = requests.get('https://example.com', proxies=proxies)

httpx 使用相同的字典格式:

python
import httpx

proxies = {
    'all://': 'http://proxy.example.com:8080',  # 匹配所有协议
}

with httpx.Client(proxies=proxies) as client:
    resp = client.get('https://example.com')

8.2 代理认证

需要认证的代理:

python
# requests:在 URL 中嵌入凭证
proxies = {
    'http': 'http://user:pass@proxy.example.com:8080',
    'https': 'http://user:pass@proxy.example.com:8080',
}

# httpx:通过 TrustyProxy 或 headers
proxies = httpx.Proxy(
    url='http://user:pass@proxy.example.com:8080',
    auth=('user', 'pass')
)

8.3 SSL 证书验证

默认情况下,requests 和 httpx 都会验证服务器的 SSL 证书。这是最重要的安全特性,跳过验证会使你面临中间人攻击风险。

python
import requests

# 默认行为:验证证书
resp = requests.get('https://example.com')

# 禁用验证(不推荐生产环境使用)
resp = requests.get('https://self-signed.badssl.com', verify=False)
# ⚠️ 会触发 InsecureRequestWarning

httpx 默认验证证书,且警告更严格:

python
import httpx

# 默认验证
with httpx.Client() as client:
    resp = client.get('https://example.com')

# 禁用验证(同样不推荐)
with httpx.Client(verify=False) as client:
    resp = client.get('https://self-signed.badssl.com')

8.4 自定义 CA 证书

企业内部常使用自签 CA,需要指定 CA bundle:

python
import requests

# 指定 CA bundle 路径
resp = requests.get(
    'https://internal.example.com',
    verify='/path/to/ca-bundle.crt'
)

# 也可以指定目录
resp = requests.get(
    'https://internal.example.com',
    verify='/etc/ssl/certs/'
)

httpx 同样支持:

python
import httpx

with httpx.Client(verify='/path/to/ca-bundle.crt') as client:
    resp = client.get('https://internal.example.com')

8.5 客户端证书

双向 TLS(mTLS)需要客户端证书:

python
import requests

# 方式一:pem 格式证书
resp = requests.get(
    'https://example.com',
    cert=('/path/to/client.crt', '/path/to/client.key')
)

# 方式二:p12 格式证书(需要 extra_certs)
import ssl
ssl_context = ssl.create_default_context()
ssl_context.load_cert_chain('/path/to/client.crt', '/path/to/client.key')

import httpx
transport = httpx.HTTPTransport(ssl=ssl_context)
with httpx.Client(transport=transport) as client:
    resp = client.get('https://example.com')

8.6 代理与 SSL 组合实战

python
import requests
from requests.auth import HTTPProxyAuth

proxies = {
    'http': 'http://proxy.example.com:8080',
    'https': 'http://proxy.example.com:8080',
}
auth = HTTPProxyAuth('proxyuser', 'proxypass')

resp = requests.get(
    'https://internal.example.com',
    proxies=proxies,
    auth=auth,
    verify='/etc/ssl/internal-ca.pem'
)

8.7 本章小结

  • 代理通过 proxies 字典配置,支持 http/https/all 协议;
  • 永远不要在生产环境禁用 SSL 验证(verify=False);
  • 自定义 CA bundle 可解决企业内部证书问题;
  • 客户端证书通过 cert 参数(requests)或 SSLContext(httpx)配置。

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. requests 中禁用 SSL 验证的正确写法是?

2. httpx 中配置代理的正确格式是?

3. 以下哪个做法在处理自签证书时最安全?

4. requests 的 cert 参数接受什么格式?

🛠️ 动手实践

  1. 配置代理访问 https://httpbin.org/ip,打印你的出口 IP。
  2. 尝试访问 https://self-signed.badssl.com,分别用 verify=Trueverify=False 对比结果。
  3. 编写代码加载自定义 CA 证书,访问使用自签证书的内部服务。

完成练习后,进入下一章:下一章