使用urllib.request验证HTTPS证书

时间:2014-06-23 20:04:55

标签: python ssl python-3.x https urllib

我正在尝试使用Python 3的urlopen模块中的urllib.request方法打开https网址。它似乎工作正常,但文档警告说,{#1}}和cafile都没有指定,HTTPS请求不会对服务器的证书进行任何验证"。

我猜我需要指定其中一个参数,如果我不希望我的程序容易受到中间人攻击,撤销证书问题和其他漏洞的攻击。<​​/ p>

capathcafile应该指向证书列表。我应该从哪里获得此列表?是否有任何简单和跨平台的方法来使用我的操作系统或浏览器使用的相同证书列表?

6 个答案:

答案 0 :(得分:2)

我找到了一个可以做我想做的事情的图书馆:Certifi。可以通过从命令行运行pip install certifi来安装它。

现在可以轻松地发出请求并进行验证:

import certifi
import urllib.request

urllib.request.urlopen("https://example.com/", cafile=certifi.where())

正如我所料,这会为具有有效证书的网站返回HTTPResponse对象,并为证书无效的网站引发ssl.CertificateError例外。

答案 1 :(得分:1)

您可以在http://curl.haxx.se/docs/caextract.html

下载可用于urllib格式的证书Mozilla(例如PEM格式)

答案 2 :(得分:1)

不同的Linux发行版具有不同的包名称。我在Centos和Ubuntu中测试过。这些证书包是系统更新的更新。因此,您可能只是检测哪个捆绑包可用,并将其与urlopen一起使用。

cafile = None
for i in [
    '/etc/ssl/certs/ca-bundle.crt',
    '/etc/ssl/certs/ca-certificates.crt',
]:
    if os.path.exists(i):
        cafile = i
        break
if cafile is None:
    raise RuntimeError('System CA-certificates bundle not found')

答案 3 :(得分:1)

Elias Zamarias的回答仍然有效,但给出了弃用警告:

DeprecationWarning: cafile, cpath and cadefault are deprecated, use a custom context instead.

我能够以这种方式解决相同的问题(使用Python 3.7.0):

import ssl
import urllib.request

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
response = urllib.request.urlopen("http://www.example.com", context=ssl_context)

答案 4 :(得分:0)

在python 2.7及更高版本中工作

context = ssl.create_default_context(cafile=certifi.where())
req = urllib2.urlopen(urllib2.Request(url, body, headers), context=context)

答案 5 :(得分:0)

import certifi
import ssl
import urllib.request
try:
    from urllib.request import HTTPSHandler
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    context.options |= ssl.OP_NO_SSLv2
    context.verify_mode = ssl.CERT_REQUIRED
    context.load_verify_locations(certifi.where(), None)
    https_handler = HTTPSHandler(context=context,  check_hostname=True)
    opener = urllib.request.build_opener(https_handler)
except ImportError:
    opener = urllib.request.build_opener()

opener.addheaders = [('User-agent',  YOUR_USER_AGENT)]
urllib.request.install_opener(opener)