【问题标题】:python requests verify SSL certificatepython请求验证SSL证书
【发布时间】:2019-02-21 09:42:18
【问题描述】:

我正在尝试从受 SSL 保护的 API 中提取数据。我写了一个python脚本来提取数据。事先我必须将 .p12 文件转换为 openSSL 证书。当我使用以下代码时,它工作得很好:

# ----- SCRIPT 1 -----
def pfx_to_pem(pfx_path, pfx_password):
    ''' Decrypts the .pfx file to be used with requests. '''
    with tempfile.NamedTemporaryFile(suffix='.pem') as t_pem:
        f_pem = open(t_pem.name, 'wb')
        pfx = open(pfx_path, 'rb').read()
        p12 = OpenSSL.crypto.load_pkcs12(pfx, pfx_password)
        f_pem.write(OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey()))
        f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate()))
        ca = p12.get_ca_certificates()
        if ca is not None:
            for cert in ca:
                f_pem.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert))
        f_pem.close()
        yield t_pem.name

# read some config
with open('config.json') as config_json:
    config = json.load(config_json)
    api_url = config['api_url']
    cert = config['cert']

    cert_pem_path = cert['file']
    cert_key_file = cert['pass']

# make the request
with pfx_to_pem(cert_pem_path, cert_key_file) as cert:
    r = requests.get(api_url, cert = cert)

因为我也使用相同的功能向服务器验证我的 Flask Web 服务,所以我将证书文件分成三个文件:

# ----- SCRIPT 1 -----
# get certificate
f_pem.write(OpenSSL.crypto.dump_certificate(
    OpenSSL.crypto.FILETYPE_PEM, p12.get_certificate())
)

# get keyfile
f_key.write(OpenSSL.crypto.dump_privatekey(
    OpenSSL.crypto.FILETYPE_PEM, p12.get_privatekey())
)

# get CA_BUNDLE
ca = p12.get_ca_certificates()
    if ca is not None:
        for cert in ca:
            f_ca.write(
                OpenSSL.crypto.dump_certificate(
                    OpenSSL.crypto.FILETYPE_PEM, cert
            ))

然后我使用以下代码运行 Web 服务:

# ----- SCRIPT 2 -----
context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
context.verify_mode = ssl.CERT_REQUIRED
context.load_verify_locations(cert_ca)
context.load_cert_chain(cert_pem, cert_key)

app.run(ssl_context = context, host = '0.0.0.0')

并将请求调用更改为

# ----- SCRIPT 1 -----
r = requests.get(api_url, cert = (cert_pem, cert_key), verify = cert_ca)

尝试从 API 提取数据时出现错误

requests.exceptions.SSLError: HTTPSConnectionPool(host='some.host', port=443): Max retries exceeded with url: /some/path/var?ID=xxxxxx (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:847)'),))

问题 1:我在创建 CA_BUNDLE 时做错了什么?

问题 2:我是否正确处理了 Web 服务的创建?我的目标是针对持有数据的服务器验证我的服务器,以最终能够通过推送请求接收数据。

编辑:当连接到我的网络服务(在浏览器中)时,我收到连接不安全的警告,因为证书无效,尽管我已将 .p12 证书导入浏览器。

【问题讨论】:

    标签: python flask openssl python-requests ssl-certificate


    【解决方案1】:

    所以我使用请求和 json 库来调用 API,在我的情况下,我可以设置请求以忽略证书,这很快解决了我的问题

    requests.get(url, headers=headers, verify=False) 
    

    参数 verify=False 忽略证书,但是当您运行代码时,它会显示一条警告消息作为输出,说明证书错误,因此您可以添加其他代码以不显示请求警告:

    import urllib3
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    

    我知道这不能回答您的问题,但也许您可以尝试看看没有证书您是否能够毫无问题地获取信息。

    【讨论】:

    • 用于提取数据 verify=False 有效。但你是对的,出于安全原因,我必须使用验证。但我注意到,当我将所有内容作为单个文件传递时,Web 服务仍会启动。
    • 所以你在证书的其他部分做错了,我建议你在没有使用证书的情况下理解什么是错误的(这样更容易识别)然后你把证书放回去;) 可能是一些错误的标头/正文值或跨域调用(我已经遇到了这个问题,你只需要在你的 flash API 服务上允许 CORS)flask-cors.readthedocs.io/en/latest
    • 您好,我有一个请求,通过禁用设置选项中的“SSL 证书验证”,我可以在 Postman 中回复 post 请求。但是,如果我得到 Postman 提供的 python 请求代码,我将收到“SSL 例程”、“tls_process_server_certificate”、“证书验证失败”错误,并且在这种情况下添加“verify=False”没有帮助,是有什么解决方案可以在 python 请求脚本中获取 Postman 的响应?
    • 尝试在导入过程中添加这个:urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    猜你喜欢
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 1970-01-01
    • 2021-12-10
    • 2013-09-30
    • 2013-10-12
    • 2011-03-07
    相关资源
    最近更新 更多