You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用requests.post携带PFX证书发送JSON遇401未授权问题

问题

使用Python的requests.post向API发送JSON对象并附加PFX格式SSL证书时,服务器始终返回401未授权错误,错误信息如下:

"status":"401",
"message":"{"error":"unauthorized","error_description":"Not valid credentials supplied. Please check request parameters."}"

确认JSON对象构造无误,相关代码如下:

from contextlib import contextmanager
from pathlib import Path
from tempfile import NamedTemporaryFile
import json
import requests
from cryptography.hazmat.primitives.serialization import Encoding, PrivateFormat, NoEncryption
from cryptography.hazmat.primitives.serialization.pkcs12 import load_key_and_certificates

cert_file = "certificado/cert.pfx"
cert_password = "xxxxx"
    

headers = {
    'accept': 'application/json'
}


@contextmanager
def pfx_to_pem(pfx_path, pfx_password):
    ''' Decrypts the .pfx file to be used with requests. '''
    pfx = Path(pfx_path).read_bytes()
    private_key, main_cert, add_certs = load_key_and_certificates(pfx, pfx_password.encode('utf-8'), None)
    
    with NamedTemporaryFile(suffix='.pem', delete=False) as t_pem:
        with open(t_pem.name, 'wb') as f_pem:
            f_pem.write(private_key.private_bytes(Encoding.PEM, PrivateFormat.PKCS8, NoEncryption()))
            f_pem.write(main_cert.public_bytes(Encoding.PEM))
            for ca in add_certs:
                f_pem.write(ca.public_bytes(Encoding.PEM))
        yield t_pem.name


jsonObj = {"Things to send"}
myURL = "https://myurl.com"

with pfx_to_pem(cert_file, cert_password) as cert:
    response = requests.post(myURL, json=jsonObj, cert=cert, headers= headers)
    if response.status_code == 200:
        response= json.loads(response.text)
        print("Response OK!")
        print(response)
         
    else:
        print(response.status_code, response.text)
排查方向与解决方法
  • 验证PFX转PEM的完整性
    用openssl pkcs12 -in cert.pfx -out cert.pem -nodes命令手动转换PFX文件,对比代码生成的PEM文件内容是否一致。如果手动转换后请求能成功,说明代码里的转换逻辑存在问题。

  • 调整cert参数的使用方式
    requests的cert参数支持两种形式:单个文件路径(需同时包含私钥和证书),或者元组形式(分别传入证书路径和私钥路径)。尝试将转换后的内容拆分为单独的证书文件和私钥文件,用cert=(cert_path, key_path)的方式传入,部分服务器对这种形式的兼容性更好。另外,注意证书链的顺序,有些服务器要求先写CA证书,再写用户证书,最后写私钥。

  • 检查是否需要额外身份验证
    部分API除了SSL客户端证书,还要求在请求头中添加API密钥或Basic Auth。查看API文档,确认是否需要额外的Authorization头,比如headers['Authorization'] = 'Bearer {token}',或者生成Basic Auth的编码值添加到请求头。

  • 确认JSON请求体的准确性
    用json.dumps(jsonObj)打印实际发送的JSON字符串,对比API要求的字段名、嵌套结构、必填项是否完全匹配。requests.post的json参数会自动设置Content-Type: application/json头,但如果服务器有特殊要求,可手动显式添加该头到headers中。

  • 开启请求调试日志
    开启调试日志查看请求细节,确认证书是否正确加载、请求头和请求体是否符合要求:

    import logging
    import http.client
    
    http.client.HTTPConnection.debuglevel = 1
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger("requests.packages.urllib3")
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True
    

    运行代码后查看日志,定位请求中的异常点。

内容的提问来源于stack exchange,提问作者Francisco Marques

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 02:12:54