Python3: 发送带证书的http/https request请求

本文介绍如何将P12证书转换为PEM格式,并使用Python的requests库进行HTTPS请求。通过提供的Python脚本,可以实现从P12到PEM的转换,并利用PEM证书发起带证书验证的HTTP/HTTPS请求。

python3 的requests请求支持携带的证书种类是pem,如果拥有的证书不是pem,需要先转为pem。

:param cert: (optional) if String, path to ssl client cert file (.pem). If Tuple, ('cert', 'key') pair.
以下代码实现了p12证书转pem证书,发送带证书的http/https request请求。
import requests, OpenSSL

def p12_to_pem(certname, pwd):
    pem_name = certname + ".pem"
    f_pem = open(pem_name, 'wb')
    p12file = certname + ".p12"
    p12 = OpenSSL.crypto.load_pkcs12(open(p12file, 'rb').read(), pwd)
    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()
    return pem_name

def post_cert_request(url,data,header,certname,pwd):
    if(certname!=""):
        cert = p12_to_pem(certname,pwd)
    else:
        cert = None
    r = requests.post(url, data=data, headers=header, cert=cert)
    print(r.content)

if __name__=="__main__":
    post_cert_request("url","data","header","certname","pwd")

<think>我们需要使用Python发送一个有SSL客户端证书HTTPS请求。这通常用于双向TLS认证,其中服务器会验证客户端的证书。 在Python中,我们可以使用`requests`库来发送HTTPS请求,并且可以通过指定证书和密钥文件来添加客户端证书。 如果使用标准库`urllib`也可以,但`requests`更简洁。 步骤: 1. 准备客户端证书文件(通常是一个.crt或.pem文件)和私钥文件(.key文件)。有时证书和私钥可能在同一文件中。 2. 使用`requests`库发送请求时,通过`cert`参数指定证书和私钥的路径(如果是分开的两个文件,则传入一个元组(cert_path, key_path);如果是在同一个文件,则传入该文件的路径)。 3. 如果服务器使用的是自签名证书,我们可能需要禁用证书验证(verify=False),但在生产环境中不推荐这样做。更好的做法是将服务器的CA证书添加到信任链中,通过`verify`参数指定CA证书路径。 注意:如果私钥是加密的(有密码),`requests`库目前不支持直接传入密码,需要先解密。我们可以使用其他库(如`cryptography`)来解密,或者使用`urllib3`的相应功能,但这样会复杂一些。通常建议使用未加密的私钥(在安全的环境下)或通过其他方式处理。 示例代码(假设证书和私钥是分开的两个文件): ```python import requests # 客户端证书和私钥文件路径 cert_file = &#39;/path/to/client.crt&#39; key_file = &#39;/path/to/client.key&#39; # 或者如果证书和私钥在同一个文件中 # cert_file = &#39;/path/to/client.pem&#39; # 目标URL url = &#39;https://example.com/api&#39; # 如果需要,可以指定服务器的CA证书(用于验证服务器证书) # ca_cert = &#39;/path/to/ca.crt&#39; # 发送GET请求(如果是POST,则使用requests.post) # 如果证书和私钥分开,使用元组 response = requests.get(url, cert=(cert_file, key_file), verify=True) # 如果服务器使用公共CA签名的证书,verify=True(默认)会使用系统CA证书来验证服务器。如果使用自签名,可以设置verify=False(不安全)或指定CA证书文件 # 例如:verify=ca_cert # 打印响应 print(response.status_code) print(response.text) ``` 如果证书和私钥在同一个文件中,则可以直接传入该文件路径: ```python response = requests.get(url, cert=&#39;/path/to/client.pem&#39;, verify=True) ``` 注意:私钥文件必须是未加密的(即没有密码保护)。如果私钥有密码,我们需要先解密。可以使用`cryptography`库来加载加密的私钥并解密,但`requests`本身不支持。因此,通常的做法是临时解密或者使用无密码的私钥(在安全环境下)。 如果必须使用加密的私钥,我们可以使用以下方法(但需要额外处理): 1. 使用`cryptography`库加载加密私钥,然后将其解密并写入一个临时文件(注意安全),再使用这个临时文件。 2. 或者使用`urllib3`结合`ssl`模块,但代码会复杂一些。 由于这种情况较少,且涉及安全,这里不展开。推荐在安全的环境下使用无密码的私钥。 另外,如果服务器要求客户端证书,而你没有提供,服务器会返回错误(如400 Bad Request或403 Forbidden等)。如果证书无效(例如过期、不被信任等),也会出现错误。 示例中我们使用了`requests`库,如果环境中没有安装,需要先安装: ```bash pip install requests ``` 解释代码: - 我们导入了`requests`库。 - 指定了客户端证书和私钥的路径(分开或合并)。 - 使用`requests.get`(或其他方法)发送请求,并通过`cert`参数提供客户端证书。 - `verify`参数用于控制是否验证服务器证书。可以设置为`True`(默认,使用系统CA证书)、`False`(不验证,不安全)或CA证书文件路径。 注意:在实际应用中,请确保私钥文件的安全,不要泄露。 相关问题: 1. 如何发送有客户端证书的POST请求? 2. 如果私钥文件有密码保护,如何在Python发送有客户端证书HTTPS请求3. 如何使用Python标准库(不使用requests发送有客户端证书HTTPS请求? 4. 在双向TLS认证中,服务器证书的验证流程是怎样的?</think>### Python发送有SSL证书HTTPS请求Python发送有SSL客户端证书HTTPS请求,可以使用`requests`库(推荐)或标准库`urllib.request`。以下是两种方法的实现: #### 方法1:使用requests库(推荐) ```python import requests # 证书配置 cert_file = &#39;/path/to/client.crt&#39; # 客户端证书 key_file = &#39;/path/to/client.key&#39; # 私钥文件 ca_bundle = &#39;/path/to/ca_bundle.crt&#39; # 可选的CA证书包 # 目标URL url = &#39;https://example.com/api&#39; # 发送请求 try: response = requests.get( url, cert=(cert_file, key_file), # 客户端证书和私钥 verify=ca_bundle or True # 验证服务器证书 ) print(f"状态码: {response.status_code}") print(f"响应内容: {response.text}") except requests.exceptions.SSLError as e: print(f"SSL错误: {e}") except requests.exceptions.RequestException as e: print(f"请求失败: {e}") ``` #### 方法2:使用urllib标准库 ```python import ssl from urllib.request import Request, urlopen # 证书配置 cert_file = &#39;/path/to/client.crt&#39; # 客户端证书 key_file = &#39;/path/to/client.key&#39; # 私钥文件 ca_bundle = &#39;/path/to/ca_bundle.crt&#39; # CA证书包 # 创建SSL上下文 context = ssl.create_default_context() context.load_cert_chain(certfile=cert_file, keyfile=key_file) context.load_verify_locations(cafile=ca_bundle) # 目标URL url = &#39;https://example.com/api&#39; # 发送请求 try: request = Request(url) with urlopen(request, context=context) as response: print(f"状态码: {response.status}") print(f"响应内容: {response.read().decode(&#39;utf-8&#39;)}") except ssl.SSLError as e: print(f"SSL错误: {e}") except Exception as e: print(f"请求失败: {e}") ``` ### 关键参数说明: 1. **客户端证书** (`cert_file`) - PEM格式的证书文件,包含客户端的公钥 - 用于向服务器证明客户端身份 2. **私钥文件** (`key_file`) - 与证书配对的私钥文件 - 必须是非加密的PEM格式(requests库限制) 3. **CA证书包** (`ca_bundle`) - 包含信任的根证书和中间证书 - 用于验证服务器证书的合法性 - 如果设为`True`(默认),使用系统CA证书 ### 证书格式要求: - **客户端证书+私钥**:可以是分开的`.crt`和`.key`文件,或合并的`.pem`文件 - **文件编码**:必须是PEM格式(Base64编码文本),而非DER二进制格式 - **私钥要求**:requests库要求私钥**不能有密码保护**。如需密码保护,需使用`cryptography`库提前解密 ### 常见错误处理: - **SSL验证失败**:检查CA证书包是否包含服务器证书链的所有证书 - **证书不匹配**:确保证书私钥配对(使用`openssl rsa -in key.key -check`验证) - **协议不兼容**:可通过SSL上下文配置协议版本: ```python context = ssl.create_default_context() context.set_ciphers(&#39;ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20&#39;) context.minimum_version = ssl.TLSVersion.TLSv1_2 ``` ### 最佳实践: 1. 将证书存储在安全位置(如密钥管理系统) 2. 生产环境中避免禁用证书验证(`verify=False`) 3. 使用证书有效期监控 4. 对于高性能场景,复用SSL上下文对象 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值