【问题标题】:Python Request with Cert带证书的 Python 请求
【发布时间】:2022-12-15 12:48:32
【问题描述】:

我正在尝试将证书嵌入文件中,而不是通过文件调用它,因为在我需要放置脚本的地方,调用文件可能无法正常工作。

这是当前代码:

cert = (r"example.crt",r"example.key")
r = requests.post("https://example.com",headers=pHeaders,json=data,cert=cert,verify=False)

这是可行的,但是我正在寻找类似以下代码的内容:

cert = """--- cert file in string format ---"""
key = """--- key file in string format ---"""
r = requests.post("https://example.com",headers=pHeaders,json=data,cert=cert,verify=False)

但是,证书功能需要一个文件。有解决方法吗?

【问题讨论】:

    标签: python-3.x python-requests ssl-certificate


    【解决方案1】:

    尝试使用tempfile.NamedTemporaryFile()

    import requests
    import tempfile
    
    cert = """--- cert file in string format ---"""
    key = """--- key file in string format ---"""
    
    with tempfile.NamedTemporaryFile() as f_cert, tempfile.NamedTemporaryFile() as f_key:
        f_cert.write(cert.encode("utf-8"))
        f_cert.seek(0)
    
        f_key.write(key.encode("utf-8"))
        f_key.seek(0)
    
        r = requests.get(
            "https://example.com", cert=(f_cert.name, f_key.name)
        )
    

    【讨论】:

    • 使用这种方法时出现以下错误:path should be string, bytes, os.PathLike or integer, not _TemporaryFileWrapper
    • @WianCrous 你用过f_cert.namef_key.name吗? (注意.name
    • 我确实将其更改为 f_cert.name 和 f_key.name,现在出现以下错误:requests.exceptions.ConnectionError: ('Connection aborted.', PermissionError(13, 'Permission denied'))
    【解决方案2】:

    有一个 hack 可以使新版本的 requestpyOpenSSL 能够处理序列化的 base64 编码的证书/密钥。 您可以使用以下命令轻松序列化证书和密钥:

    ~$cat my_precious_private_key.key | base64 
    
    from OpenSSL.crypto import FILETYPE_PEM, load_certificate, load_privatekey
    import base64
    
    BASE64_CERT_STRING = "<serialized cert>"
    BASE64_KEY_STRING = "<serialized key>"
    
    # Hack to use old pyopenssl with new urllib3
    import urllib3.contrib.pyopenssl
    urllib3.contrib.pyopenssl.inject_into_urllib3()
    
    class Pkcs12Context(
              requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context
          ): 
        def __init__(self, method):
            super().__init__(method)
            self.use_certificate(load_certificate(FILETYPE_PEM, base64.b64decode(BASE64_CERT_STRING)))
            self.use_privatekey(load_privatekey(FILETYPE_PEM, base64.b64decode(BASE64_KEY_STRING)))
     
    # Save the original context, then replace the request context with your handmade one
    original_context = requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context
    requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context = Pkcs12Context
    
    #  Nice! Make a call: 
    response = requests.post(
        url, 
        headers={"Content-Type": "text/xml"}, #  or "Application/text"
        data=payload,
        timeout=60)
    
    pass  # — process the response
    
    # Do not forget to reset the original context!
    requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context = original_context
    

    还有 FILETYPE_TEXT is available 键。

    【讨论】:

      猜你喜欢
      • 2021-02-10
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-30
      相关资源
      最近更新 更多