我试图让Pythonurllib.request.urlopen(url, ca*)
执行证书检查,但忽略主机名不匹配。
(这是必需的,因为可以通过公用IP,专用IP,主机名或FQDN访问主机,并且我不想依靠证书来拥有所有这些有效字段)
根据官方文档,我可以使用带有的自定义开启程序,以HTTPSHandler
禁用主机名检查(https://docs.python.org/3/library/urllib.request.html)
但是,由于Python Issue18543(http://bugs.python.org/issue18543),urllib.request.urlopen()
如果指定了任何ca *参数,它将忽略已安装的opener。
我的问题是:
解决此问题的最佳方法是什么?我应该尝试重写该urllib.request.urlopen()
方法吗?如果是这样,该如何以pythonic方式完成?还有其他选择吗?我真的不想重写和维护很多基本代码。
到目前为止,我的代码如下(无法正常工作):
import ssl
import urllib.request # used to be import urllib2 in python 2.x
#create an HTTPS Handler that does not check the hostname
https_handler = urllib.request.HTTPSHandler(debuglevel=0, check_hostname=False)
opener = urllib.request.build_opener(https_handler)
urllib.request.install_opener(opener)
# PROBLEM is that this opener will not be used by urlopen.
# solution: override the urlopen method?
# verify server certificate
try:
urllib.request.urlopen("https://127.0.0.1:4443", cafile="cert.pem")
except ssl.CertificateError as e:
print ("Certificate Error:",e)
return -1
return 0
运行代码会给出有关主机名不匹配的证书错误。
这个问题也在这里讨论:http : //www.gossamer-threads.com/lists/python/bugs/1005966?do=post_view_threaded
特别是这篇文章提出了一种解决方法:http : //www.gossamer-threads.com/lists/python/bugs/1006048? do = post_view_threaded# 1006048
看来这并不是一件容易的事,从长远来看,大多数解决方案都不可靠。
我想发布选择解决该问题的解决方案。
首先,我选择使用urllib3库(https://pypi.python.org/pypi/urllib3)。
从文档中,我发现最容易使用PoolManager:
import urllib3
http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED',
ca_certs="cert.pem",
assert_hostname=False)
try:
r = http.request('GET', 'https://127.0.0.1:4443/')
print("STATUS:", r.status)
print("Certificate verification NO HOSTNAME successful")
except urllib3.exceptions.SSLError as e:
print ("SSL Error:", e)
return -1
return 0
请注意,在urllib3版本1.10中将忽略assert_hostname = False:https : //github.com/shazow/urllib3/issues/524
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句