使用 urllib.request 验证 HTTPS 证书

Eli*_*ria 9 python ssl https urllib python-3.x

我正在尝试使用urlopenPython 3urllib.request模块中的方法打开一个 https URL 。它似乎工作正常,但文档警告“[i]如果既未指定也cafilecapath指定,HTTPS 请求将不会对服务器的证书进行任何验证”。

如果我不希望我的程序容易受到中间人攻击、吊销证书问题和其他漏洞,我猜我需要指定这些参数之一。

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

小智 8

适用于 python 2.7 及更高版本

context = ssl.create_default_context(cafile=certifi.where())
req = urllib2.urlopen(urllib2.Request(url, body, headers), context=context)
Run Code Online (Sandbox Code Playgroud)


Eli*_*ria 5

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

提出请求并验证它们现在很容易:

import certifi
import urllib.request

urllib.request.urlopen("https://example.com/", cafile=certifi.where())
Run Code Online (Sandbox Code Playgroud)

正如我所料,这会HTTPResponse为具有有效证书的站点返回一个对象,并ssl.CertificateError为具有无效证书的站点引发异常。


Inc*_*tor 5

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

DeprecationWarning: cafile, cpath and cadefault are deprecated, use a custom context instead.
Run Code Online (Sandbox Code Playgroud)

我能够用这种方式解决同样的问题(使用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)
Run Code Online (Sandbox Code Playgroud)