python请求验证SSL证书

python请求验证SSL证书,python,flask,openssl,python-requests,ssl-certificate,Python,Flask,Openssl,Python Requests,Ssl Certificate,我试图从一个受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(s

我试图从一个受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服务的创建?我的目标是根据保存数据的服务器验证我的服务器,以便最终能够通过推送请求接收数据


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

因此我使用请求和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)嗨,我有一个请求,通过禁用设置选项中的“SSL证书验证”,在邮递员中为我提供post请求的响应。但是,如果我得到邮递员提供的python请求代码,我将收到“SSL例程”、“tls\u进程\u服务器\u证书”、“证书验证失败”错误,在这种情况下添加“verify=False”没有帮助,是否有任何解决方案可以在python请求脚本中获取邮递员的响应?请尝试在导入过程中添加此选项:urllib3.disable_warnings(urllib3.exceptions.SecureRequestWarning)