Python使用requests请求时ssl验证失败

在Python网络请求开发中,使用requests库调用HTTPS接口时,SSL验证失败 是高频棘手问题。无论是爬虫采集、接口调试还是生产环境调用,均可能因证书信任、协议兼容、环境配置等问题触发验证报错,导致请求中断。这类问题看似复杂,实则根源可归纳为证书有效性、本地信任机制、协议适配三类场景。当使用requests库遇到SSL验证失败时,可以通过以下几种方式解决。

一. 解决办法

1. 临时禁用SSL验证(不推荐用于生产环境)

python 复制代码
import requests

# 方法1:全局禁用
response = requests.get('https://example.com', verify=False)

# 方法2:对于特定请求禁用
response = requests.get('https://example.com', verify=False)

# 方法3:使用上下文管理器临时禁用
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)  # 禁用警告
response = requests.get('https://example.com', verify=False)

2. 指定自定义CA证书

python 复制代码
import requests

# 指定证书文件路径
response = requests.get('https://example.com', 
                       verify='/path/to/certificate.pem')

# 指定证书目录
response = requests.get('https://example.com', 
                       verify='/path/to/certs/')

# 使用系统证书(Windows/Mac/Linux)
response = requests.get('https://example.com', 
                       verify=True)  # 默认就是True

3. 安装并更新证书(推荐)

方法1:使用certifi库(推荐)

python 复制代码
import requests
import certifi

# 使用certifi提供的证书
response = requests.get('https://example.com', 
                       verify=certifi.where())

# 更新certifi证书
# 在命令行执行:
# pip install --upgrade certifi

方法2:手动安装证书

bash 复制代码
# Ubuntu/Debian
sudo apt-get install ca-certificates

# CentOS/RHEL
sudo yum install ca-certificates

# macOS
# 证书通常已经内置,可以通过钥匙串访问管理

# Windows
# 从受信任的CA机构下载证书

4. 设置环境变量(开发环境)

python 复制代码
import os
os.environ['REQUESTS_CA_BUNDLE'] = '/path/to/certificate.pem'
os.environ['SSL_CERT_FILE'] = '/path/to/certificate.pem'

# 或者在运行前设置环境变量
# export REQUESTS_CA_BUNDLE=/path/to/certificate.pem

5. 使用自定义SSL适配器(高级)

python 复制代码
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
import ssl

class SSLAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        ctx = ssl.create_default_context()
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE
        kwargs['ssl_context'] = ctx
        return super().init_poolmanager(*args, **kwargs)

session = requests.Session()
session.mount('https://', SSLAdapter())
response = session.get('https://example.com')

二. 常见问题解决方案

问题1:自签名证书

python 复制代码
# 导出服务器的证书
# openssl s_client -connect example.com:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM > mycert.pem

# 然后使用该证书
response = requests.get('https://example.com', 
                       verify='mycert.pem')

问题2:证书路径问题

python 复制代码
import os

# 查找证书路径
print(requests.certs.where())  # requests使用的证书路径
print(certifi.where())         # certifi提供的证书路径

# 设置requests使用系统证书
if os.name == 'nt':  # Windows
    cert_path = 'C:/Python39/Lib/site-packages/certifi/cacert.pem'
else:  # Linux/Mac
    cert_path = '/usr/local/lib/python3.9/site-packages/certifi/cacert.pem'
    
response = requests.get('https://example.com', verify=cert_path)

问题3:代理环境下的SSL问题

python 复制代码
import requests

proxies = {
    'http': 'http://proxy.example.com:8080',
    'https': 'http://proxy.example.com:8080',
}

# 可能需要同时禁用SSL验证
response = requests.get('https://example.com', 
                       proxies=proxies, 
                       verify=False)

三. 最佳实践代码示例

python 复制代码
import requests
import certifi
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import urllib3
import warnings

# 禁用SSL警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
warnings.filterwarnings('ignore', message='Unverified HTTPS request')

def create_secure_session():
    """创建安全的requests会话"""
    session = requests.Session()
    
    # 设置重试策略
    retry_strategy = Retry(
        total=3,
        backoff_factor=1,
        status_forcelist=[429, 500, 502, 503, 504],
    )
    adapter = HTTPAdapter(max_retries=retry_strategy)
    session.mount("https://", adapter)
    session.mount("http://", adapter)
    
    return session

def make_request(url, use_ssl=True):
    """安全的请求函数"""
    session = create_secure_session()
    
    try:
        if use_ssl:
            # 使用certifi证书
            response = session.get(url, verify=certifi.where(), timeout=30)
        else:
            # 开发环境禁用SSL
            response = session.get(url, verify=False, timeout=30)
        
        response.raise_for_status()  # 检查HTTP错误
        return response
        
    except requests.exceptions.SSLError as e:
        print(f"SSL错误: {e}")
        # 尝试使用系统证书
        try:
            response = session.get(url, verify=True, timeout=30)
            return response
        except:
            raise
    except requests.exceptions.RequestException as e:
        print(f"请求错误: {e}")
        raise

# 使用示例
try:
    response = make_request('https://example.com')
    print(response.text)
except Exception as e:
    print(f"请求失败: {e}")

四. 检测和诊断SSL问题

python 复制代码
import ssl
import requests

def check_ssl_info(url):
    """检查SSL证书信息"""
    try:
        response = requests.get(url, timeout=10)
        print(f"URL: {url}")
        print(f"状态码: {response.status_code}")
        print(f"使用的证书: {response.raw.connection.sock.getpeercert()}")
    except requests.exceptions.SSLError as e:
        print(f"SSL错误详情: {e}")
        print(f"错误类型: {type(e).__name__}")
    except Exception as e:
        print(f"其他错误: {e}")

# 检查requests使用的证书库
print(f"requests证书路径: {requests.certs.where()}")
print(f"OpenSSL版本: {ssl.OPENSSL_VERSION}")

# 检查特定网站的SSL
check_ssl_info('https://www.google.com')

注意事项:

  • 生产环境不要 使用verify=False,这会存在安全风险
  • 开发/测试环境可以临时禁用SSL验证
  • 建议使用certifi库来管理证书
  • 定期更新证书:pip install --upgrade certifi

总结

在实际开发中,建议先排查证书有效性与本地信任配置,再优化协议适配,既能高效解决问题,又能兼顾系统安全性与稳定性。

相关推荐
青 春 记 忆5 小时前
Dify Docker Compose 通用无损升级指南:从备份、双版本预演到切换与回滚
运维·人工智能·python·docker·容器
GlueNa2SiO35 小时前
03-Flask模板引擎Jinja2详解
笔记·python·flask
临沂GEO7 小时前
GEO搜索优化科普|正规地理位置流量运营入门指南
大数据·人工智能·python·流量运营
大模型码小白7 小时前
Spring AI Tool 实现自然语言操作 MySQL 数据库详解
服务器·开发语言·数据库·人工智能·python·mysql·spring
荷蒲9 小时前
【小白量化Qbuddy】利用AI学习中文Python
人工智能·python·学习
数据狐(Datafox)10 小时前
京东商品列表API技术解析与落地应用(含标准 JSON 示例)
java·大数据·前端·人工智能·python·数据分析·json
量化吞吐机10 小时前
2026年下半年手工交易规则走向量化表达,产品该先接住哪一步
人工智能·python
Metaphor69211 小时前
使用 Python 读取和删除 Excel 文件属性
python·excel
迷迭香yy12 小时前
Python构建转融券多空识别系统从接口到因子的全流程 IG50免费开源股票数据API接口
开发语言·python·开源
月光船幽幽12 小时前
真实即粗糙,光滑是伪造
人工智能·python