Ignore certificate validation with urllib3

寵の児 提交于 2019-11-30 05:21:33

问题


I'm using urllib3 against private services that have self signed certificates. Is there any way to have urllib3 ignore the certificate errors and make the request anyways?

import urllib3
c = urllib3.HTTPSConnectionPool('10.0.3.168', port=9001)
c.request('GET', '/')

When using the following:

import urllib3
c = urllib3.HTTPSConnectionPool('10.0.3.168', port=9001, cert_reqs='CERT_NONE')
c.request('GET', '/')

The following error is raised:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3/dist-packages/urllib3/request.py", line 67, in request
    **urlopen_kw)
  File "/usr/lib/python3/dist-packages/urllib3/request.py", line 80, in request_encode_url
    return self.urlopen(method, url, **urlopen_kw)
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 415, in urlopen
    body=body, headers=headers)
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 267, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/lib/python3.3/http/client.py", line 1061, in request
    self._send_request(method, url, body, headers)
  File "/usr/lib/python3.3/http/client.py", line 1099, in _send_request
    self.endheaders(body)
  File "/usr/lib/python3.3/http/client.py", line 1057, in endheaders
    self._send_output(message_body)
  File "/usr/lib/python3.3/http/client.py", line 902, in _send_output
    self.send(msg)
  File "/usr/lib/python3.3/http/client.py", line 840, in send
    self.connect()
  File "/usr/lib/python3/dist-packages/urllib3/connectionpool.py", line 103, in connect
    match_hostname(self.sock.getpeercert(), self.host)
  File "/usr/lib/python3/dist-packages/urllib3/packages/ssl_match_hostname/__init__.py", line 32, in match_hostname
    raise ValueError("empty or no certificate")
ValueError: empty or no certificate

Using cURL I'm able to get the expected response from the service

$ curl -k https://10.0.3.168:9001/
Please read the documentation for API endpoints

回答1:


Try following code:

import urllib3
c = urllib3.HTTPSConnectionPool('10.0.3.168', port=9001, cert_reqs='CERT_NONE',
                                assert_hostname=False)
c.request('GET', '/')

See Setting assert_hostname to False will disable SSL hostname verification




回答2:


Try to instanciate your connection pool this way:

HTTPSConnectionPool(self.host, self.port, cert_reqs=ssl.CERT_NONE)

or this way:

HTTPSConnectionPool(self.host, self.port, cert_reqs='CERT_NONE')

Source: https://github.com/shazow/urllib3/blob/master/test/with_dummyserver/test_https.py


EDIT (after seeing your edit):

It looks like the remote host didn't send a certificate (is it possible?). This is the code (from urllib3) which raised an exception:

def match_hostname(cert, hostname):
    """Verify that *cert* (in decoded format as returned by
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 rules
are mostly followed, but IP addresses are not accepted for *hostname*.

CertificateError is raised on failure. On success, the function
returns nothing.
"""
    if not cert:
        raise ValueError("empty or no certificate")

So it looks like cert is empty, which means that self.sock.getpeercert() returned an empty string.



来源:https://stackoverflow.com/questions/18061640/ignore-certificate-validation-with-urllib3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!