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

总结

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

相关推荐
喵手3 小时前
Python爬虫零基础入门【第九章:实战项目教学·第15节】搜索页采集:关键词队列 + 结果去重 + 反爬友好策略!
爬虫·python·爬虫实战·python爬虫工程化实战·零基础python爬虫教学·搜索页采集·关键词队列
Suchadar3 小时前
if判断语句——Python
开发语言·python
ʚB҉L҉A҉C҉K҉.҉基҉德҉^҉大3 小时前
自动化机器学习(AutoML)库TPOT使用指南
jvm·数据库·python
喵手4 小时前
Python爬虫零基础入门【第九章:实战项目教学·第14节】表格型页面采集:多列、多行、跨页(通用表格解析)!
爬虫·python·python爬虫实战·python爬虫工程化实战·python爬虫零基础入门·表格型页面采集·通用表格解析
0思必得04 小时前
[Web自动化] 爬虫之API请求
前端·爬虫·python·selenium·自动化
莫问前路漫漫4 小时前
WinMerge v2.16.41 中文绿色版深度解析:文件对比与合并的全能工具
java·开发语言·python·jdk·ai编程
木头左4 小时前
Backtrader框架下的指数期权备兑策略资金管理实现与风险控制
python
玄同7654 小时前
LangChain 核心组件全解析:构建大模型应用的 “乐高积木”
人工智能·python·语言模型·langchain·llm·nlp·知识图谱
喵手4 小时前
Python爬虫实战:从零构建 Hacker News 数据采集系统:API vs 爬虫的技术抉择!(附CSV导出 + SQLite 存储)!
爬虫·python·爬虫实战·hacker news·python爬虫工程化实战·零基础python爬虫教学·csv导出
测试老哥5 小时前
软件测试之功能测试详解
自动化测试·软件测试·python·功能测试·测试工具·职场和发展·测试用例