Python urllib3和requests发送HTTPS请求时出现SSLError或InsecureRequestWarning
目录
- 问题及原因分析
- 优先考虑的解决方法:
- 下载证书
- 使用证书
- 手动获取证书
- 不推荐使用的备用解决方法:
- 关闭方法
- 衍生问题
- 参考文档
问题及原因分析
在我们通过urllib3和requests进行HTTPS请求时,可能会出现SSLError的错误:
示例1 找不到对应的本地证书
Caused by SSLError(SSLCertVerificationError(1,
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate
示例2 服务端证书过期
Caused by SSLError(SSLCertVerificationError(1,
'[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: certificate has expired
SSL为安全套接层,是HTTPS的安全基础。当证书验证失败,urlib3和requests就会抛出SSL错误。
为什么证书会验证失败?这里要先说清楚HTTPS中证书的工作原理:
公钥证书,是服务端提前向第三方机构申请颁发的,由公钥和数字签名组成。服务端提供公钥,第三方机构则负责对公钥做数字签名(即用第三方机构私钥对服务端的公钥加密)。
在HTTPS请求中,服务端会将自己的公钥证书发送给客户端,客户端拿到公钥证书后,需要凭借第三方机构的公钥(也称为证书,一般会自带在操作系统或浏览器中)去验证数字签名的有效性,验证通过即可确认服务端公钥为真实有效,然后通过公钥进行安全的加密通信。
因此,证书验证失败,就是请求方无法验证服务端公钥证书的有效性,有两种原因:
1.本地缺少对应第三方机构的公钥(也称为第三方机构的证书)
2.服务端的公钥证书有误,可能已过期
第二种原因来自服务端,我们作为请求方无法解决,只能通过后面提到的方法忽略警告或不使用SSL层。
第一种则可通过下面的方法解决。
优先考虑的解决方法:
下载证书
urllib3和requests在发送https请求时都会加载默认的系统证书,但更可靠的方法是安装 Mozilla 提供的证书包。
可以直接到官方网站去下载,但更推荐安装certifi包,方便以后更新:
python -m pip install certifi
安装后可以通过certifi的方法查询证书路径
>>> import certifi>>> certifi.where()
'F:\Anaconda\lib\site-packages\certifi\cacert.pem'
使用证书
urlib3:
指定证书路径创建连接池:
http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED', //默认值,指证书必须验证通过,否则抛出SSL错误ca_certs=certifi.where() //指定证书路径
)
连接池会使用指定路径的证书,并在验证失败时抛出异常:
http.request('GET', 'https://google.com')
(No exception)
http.request('GET', 'https://expired.badssl.com')
urllib3.exceptions.SSLError ...
requests:
跟urblib3类似,只是指定证书方式有不同,通过verify参数来指定(路径也可以直接用文件的绝对路径):
requests.get('https://github.com', verify='F:\Anaconda\lib\site-packages\certifi\cacert.pem')
或者通过session全局指定:
s = requests.Session()
s.verify = 'F:\Anaconda\lib\site-packages\certifi\cacert.pem'
s.get('https://github.com')
(No exception)
s.get('https://expired.badssl.com')
urllib3.exceptions.SSLError ...
手动获取证书
如果仍然请求失败,但浏览器能正常访问,那可以直接从浏览器导出证书来使用。以谷歌浏览器为例:
1.按顺序导出证书
2.导出文件后,将文件中的公钥复制到指定的证书路径中即可
不推荐使用的备用解决方法:
强烈建议不要发出未经验证的 HTTPS 请求,因为HTTPS可以防止中间人攻击(窃听,伪装,篡改等问题)。但如果确实无法解决证书问题,那可以关闭HTTPS请求中的SSL验证,来解决该问题。
关闭方法
urllib3:
指定cert_reqs为CERT_NONE(默认为CERT_REQUIRED)
http = urllib3.PoolManager(cert_reqs = 'CERT_NONE'
)
requests:
指定verify为False(默认为True)
#单次关闭
requests.get('https://expired.badssl.com', verify=False)
<Response [200]>#全局关闭
s = requests.Session()
s.verify = False
也可以通过SSL包来关闭(urllib3和requests通用)
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
衍生问题
关闭后便可以正常请求,但是会弹出InsecureRequestWarning的警告
InsecureRequestWarning: Unverified HTTPS request is being made to host 'www.xxx.com'.
Adding certificate verification is strongly advised
如果了解风险并希望禁用这些警告,可以使用以下方法(urllib3和requests通用):
import urllib3
urllib3.disable_warnings()
或者也可以使用logging标准模块捕获警告:
logging.captureWarnings(True)
最后,还可以通过设置环境变量PYTHONWARNINGS来限制该级别的警告 。
另外,上述方法也会同时禁用下列警告:
InsecurePlatformWarning
这发生在具有过时ssl模块的 Python 2 平台上。这些较旧的ssl模块可能会导致一些不安全的请求在它们应该失败的时候成功,而安全的请求则会在它们应该成功的地方失败
SNIMissingWarning
这发生在早于 2.7.9 的 Python 2 版本上。这些旧版本缺乏SNI支持。这可能会导致服务器提供客户端认为无效的证书
这两个警告对应问题的解决方法可以去官网文档查看
参考文档
urllib3: https://urllib3.readthedocs.io/en/1.26.x/user-guide.html#
request:https://requests.readthedocs.io/en/latest/user/advanced/
Python urllib3和requests发送HTTPS请求时出现SSLError或InsecureRequestWarning相关推荐
- 【Spring】Feign客户端发送HTTPS请求绕过认证
1.概述 转载:https://www.jianshu.com/p/ea627708ab52 一个Spring Boot项目,为了使用Harbor仓库,起初通过Spring RestTemplate完 ...
- python post请求实例_Python使用requests发送POST请求实例代码
本文研究的主要是Python使用requests发送POST请求的相关内容,具体介绍如下. 一个http请求包括三个部分,为别为请求行,请求报头,消息主体,类似以下这样: 请求行 请求报头 消息主体 ...
- requests发送post请求的一些疑点
requests发送post请求的一些疑点 前言 在Python爬虫中,使用requests发送请求,访问指定网站,是常见的做法.一般是发送GET请求或者POST请求,对于GET请求没有什么好说的,而 ...
- VS2015编译Poco+openssl,使用Poco发送HTTPS请求
下载源码.安装Openssl 下载Poco源码 git clone https://github.com/pocoproject/poco.git openssl下载安装: 下载地址:http://s ...
- requests发送http请求
requests发送http请求 发送请求:(数据获取.乱码解决) import requests response = requests.get('http://www.baidu.com') # ...
- HttpClient发送Https请求报 : unable to find valid certification path to requested target
一.场景 近期在对接第三方接口时,通过HttpClient发送Https请求报 : unable to find valid certification path to requested tar ...
- 国美金融贷款通过TCP建立连接,国美金融贷款发送HTTPS请求
国美金融贷款https通信时,首先建立ssl层的连接,客户端将ssl版本号和加密组件发到服务器端,服务器端收到后对ssl版本号和加密组件进行匹配,同时国美金融贷款将CA证书及密钥发送到客户端. 国美金 ...
- 解决 QT 发送 HTTP 请求时遇到 qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed 问题
解决 QT 发送 HTTP 请求时遇到 qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initilization failed 问题 ...
- RestTemplate 发送 Https 请求调用
RestTemplate 发送 Https 请求调用 个人博客:https://jacob.org.cn import org.apache.http.conn.ssl.NoopHostnameVer ...
最新文章
- Github上如何在组织中创建代码仓库,并如何授予该组织中某个小组权限?
- Unity手游:自动寻路Navmesh 跳跃 攀爬 斜坡
- 五、开始Github和码云之旅,新手如何上路
- 热榜!!!数据结构与算法:C语言版---数组与稀疏矩阵---强势来袭!
- Python —— any()函数和all()函数
- 怎样在计算机上注册dll文件,win10如何注册dll文件_win10系统dll文件怎样安装
- 安装cmsv7的具体方法
- 如何解决dubbo配置文件中Multiple annotations found at this line问题
- 对比度 css_更好的颜色和对比度可访问性CSS技巧
- 数据质量第一步—数据监控
- Tiny4412 LCD驱动(DRM+设备树)
- 使用vs2015打开以前版本的.sln工程不兼容的问题
- app软件系统开发好后有哪些盈利方式?
- Python时间序列LSTM预测系列教程(6)-单变量
- 下面这条语句一共创建了多少个对象:String bb=aa+bb+cc+dd
- 6种常见电流检测电路设计方案
- ftp服务器文件服务器,ftp服务器和文件服务器的区别
- 34、查询课程名称为数学,且分数低于60的学生姓名和分数(不重点)(自己做出)
- post方式返回文件流实现前端blob下载,responseType: ‘blob‘无效
- CentOS8提高篇8:CentOS制作U盘启动盘