如何使用urllib2.urlopen检查(不绕过)SSL证书?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用urllib2.urlopen检查(不绕过)SSL证书?相关的知识,希望对你有一定的参考价值。
我正在使用Python 2.7.13。我正在尝试连接到https://www.python.org/并使用urllib2.urlopen
验证其证书。我在此过程中收到“SSL:CERTIFICATE_VERIFY_FAILED”错误,当我尝试谷歌问题时,我似乎得到了如何绕过此安全检查的答案。但我不希望我的代码绕过它,我希望它使用证书。这是我的代码失败:
import urllib2
from contextlib import closing
import ssl
ctx = ssl.create_default_context(purpose = ssl.Purpose.SERVER_AUTH, cafile = 'www.python.org.crt')
request = urllib2.Request('https://www.python.org/')
# Produces URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)>
with closing(urllib2.urlopen(request, context = ctx)) as response:
print response.read()
cafile = 'www.python.org.crt'
是一个PEM格式的文件,正确地从-----BEGIN CERTIFICATE-----
开始。我使用https://www.python.org/从this instruction导出它并将其放入脚本的工作文件夹中。
从文档:https://docs.python.org/2/library/ssl.html#ssl._https_verify_certificates
从Python 2.7.9开始,httplib和使用它的模块(例如urllib2和xmlrpclib)默认验证在建立客户端HTTPS连接时收到的远程服务器证书。此默认验证检查证书是否由系统信任库中的证书颁发机构签名,并且所显示证书上的公用名(或主题备用名)与请求的主机匹配。
所以你不需要任何特殊的东西来验证证书。您可以看到,因为您有验证失败,这表明您正在进行验证。
那么为什么你没有成功验证?答案就在于您使用咖啡馆。 cafile参数采用一个文件覆盖系统默认的可信证书库。但要理解可信证书的重要一点,验证过程不是检查主机是在受信任的商店中,而是在受信任的商店中签名但是是证书。因此,您不需要传递实际的服务器证书,您将从python.org的证书供应商(撰写本文时的digicert)传递证书。
但实际上您甚至不需要这样做,因为系统应该附带来自许多供应商的大量可信证书。这些供应商在某种程度上受到审核(意见因程度而异 - 现在这个主题有所不同),如果将cafile参数留空,python的库将根据此设置进行验证。
所以你找到了
>>> ctx = ssl.create_default_context(purpose = ssl.Purpose.SERVER_AUTH, cafile = '/tmp/python.org.cert')
>>> urllib2.urlopen("https://www.python.org/", context = ctx)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python2.7/urllib2.py", line 429, in open
response = self._open(req, data)
File "/usr/lib/python2.7/urllib2.py", line 447, in _open
'_open', req)
File "/usr/lib/python2.7/urllib2.py", line 407, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 1241, in https_open
context=self._context)
File "/usr/lib/python2.7/urllib2.py", line 1198, in do_open
raise URLError(err)
urllib2.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)>
失败了,但是这个:
>>> ctx = ssl.create_default_context(purpose = ssl.Purpose.SERVER_AUTH,)
>>> urllib2.urlopen("https://www.python.org/", context = ctx)
<addinfourl at 140556044048504 whose fp = <socket._fileobject object at 0x7fd5c1127b50>>
作品。
最后,我想指出httplib和http.client(在python 3中),它们对于这类事情来说是更清晰的接口。
以上是关于如何使用urllib2.urlopen检查(不绕过)SSL证书?的主要内容,如果未能解决你的问题,请参考以下文章
Python:从 urllib2.urlopen 调用中获取 HTTP 标头?
urllib2.urlopen() 与 urllib.urlopen() - urllib2 在 urllib 工作时抛出 404!为啥?