模块 'requests.packages.urllib3.contrib' 没有属性 'pyopenssl'

module 'requests.packages.urllib3.contrib' has no attribute 'pyopenssl'

我正在开发一个简单的 python 脚本,它使用 base64 编码的证书和私钥。这些是脚本中的 base64 编码字符串文字。

我创建了一个 Pkcs12Context class 定义(加载证书和密钥的地方)。

class Pkcs12Context(requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context):
    def __init__(self, method):
        super(Pkcs12Context, self).__init__(method)
        self.use_certificate(load_certificate(FILETYPE_PEM, base64.b64decode(ENCODED_CERT)))
        self.use_privatekey(load_privatekey(FILETYPE_PEM, base64.b64decode(ENCODED_PRIVATEKEY)))

稍后我获取一个 json 有效负载对象并使用 jwt.encode() 对其进行签名,为其提供解码的私钥。

然后我像这样发出请求:

response = requests.post('https://<sampleapiendpoint>', headers={"Content-Type": "text/xml"}, data=signed_payload, timeout=60)

问题是当我 运行 带有 python2 的脚本时,它会出错:

Traceback (most recent call last):
  File "apirequest.py", line 171, in <module>
    response = requests.post('https://<sampleapiendpoint>', headers={"Content-Type": "text/xml"}, data=signed_payload, timeout=60)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/api.py", line 108, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/sessions.py", line 464, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/adapters.py", line 431, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:727)

如果我使用 python3,我会得到以下调用堆栈:

    Traceback (most recent call last):
  File "/Users/<username>/Projects/<folder>/<folder2>/apicall.py", line 94, in <module>
    class Pkcs12Context(requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context):
AttributeError: module 'requests.packages.urllib3.contrib' has no attribute 'pyopenssl'

我试过卸载并重新安装 pyopenssl 无济于事。 python2 和 python3 我都试过了,都没用。但是我确实怀疑 python2 正在工作,但是 certs/keys 有问题,因此握手永远不会成功(这意味着它是脚本或端点配置问题)。我还尝试了 https://github.com/certbot/certbot/issues/6328 论坛上描述的潜在解决方案,他们说尝试使用请求 2.6.0,我就是这样。 python2 版本是否实际工作,但 api 端点存在 cert/key 配置问题?为什么 python3 版本不起作用?

这里是 pip freeze 命令的输出:

certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
cryptography==36.0.1
idna==3.3
pycparser==2.21
PyJWT==2.3.0
pyOpenSSL==22.0.0
requests==2.6.0
urllib3==1.26.8

我无法直接解决这个问题。相反,它是通过以下方法解决的。我们根本不创建 Pkcs12Context,而是使用 requests.posts 方法的 certs 参数为请求调用提供证书。

response = requests.post('https://<url>',
                         cert=(SSL_CERTIFICATE_FILENAME, SSL_CERTIFICATE_PVKEY_FILENAME),
                         headers={"Content-Type": "text/xml"}, data=encoded, timeout=60)