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

Python请求需SSL证书认证的网页遇错误,求助解决

问题:Python访问需SSL客户端证书认证的端点失败

操作步骤与错误情况

  1. 初始尝试用urllib加载PKCS12证书:
import urllib
urllib.request.urlopen("https://mywebpage.com/some/endpoint", cafile = "C:/Users/Me/path/to/my/cert.p12")

报错:

ssl.SSLError: [X509: NO_CERTIFICATE_OR_CRL_FOUND] no certificate or crl found (_ssl.c:4149)

  1. 转换PKCS12为PEM格式:
    执行OpenSSL命令:
openssl pkcs12 -in "C:/Users/Me/path/to/my/cert.p12" -out "C:/Users/Me/path/to/my/cert.pem"

设置PKCS12和PEM密码一致后,尝试代码:

import urllib
urllib.request.urlopen("https://mywebpage.com/some/endpoint", cafile = "C:/Users/Me/path/to/my/cert.pem")

报错:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1007)

验证证书加载:执行ssl.SSLContext().load_verify_locations(cafile = "C:/Users/Me/path/to/my/cert.pem")无报错,证书信息已加载。

  1. 尝试使用certifi解决Windows下OpenSSL版本问题:
import ssl
import certifi
from urllib import request
request.urlopen("https://mywebpage.com/some/endpoint", 
    context = ssl.create_default_context(cafile = certifi.where()))

报错:

ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1007)

问题分析与解决方案

核心问题

你混淆了**CA证书(用于验证服务器合法性)和客户端证书(用于服务器验证你的身份)**的用途:

  • cafile参数是用来指定信任的CA证书,用于校验服务器证书是否合法;
  • 浏览器弹出的证书选择窗口,是要求你发送客户端证书给服务器,属于双向SSL认证场景,这部分你之前的代码完全没配置。

正确操作步骤

  1. 确保PEM文件包含客户端证书和私钥
    转换PKCS12时,要导出包含证书和私钥的PEM文件,执行命令时加上-nodes参数(避免私钥加密,若需加密可去掉该参数,后续加载时提供密码):
openssl pkcs12 -in "C:/Users/Me/path/to/my/cert.p12" -out "C:/Users/Me/path/to/my/client_cert.pem" -nodes
  1. 创建SSL上下文并加载客户端证书
    用ssl.SSLContext配置双向认证,同时指定信任的CA证书(服务器证书是自定义CA签发的需指定对应CA文件,公网证书可直接用默认信任链):
import ssl
from urllib import request

# 创建SSL上下文,用于服务器认证
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
# 加载客户端证书(若PEM有密码,添加password参数,如password=b"your_cert_password")
context.load_cert_chain(certfile="C:/Users/Me/path/to/my/client_cert.pem")
# 若服务器用自定义CA签发,需指定CA证书;公网证书可注释此行
# context.load_verify_locations(cafile="path/to/server_trusted_ca.pem")

# 发起请求
response = request.urlopen("https://mywebpage.com/some/endpoint", context=context)
print(response.read())
  1. 常见问题排查
  • 若仍报unable to get local issuer certificate:确认服务器的CA证书已加入信任链,或load_verify_locations指定了正确的CA文件;
  • 若报handshake failure:检查客户端证书是否包含完整链(含中间证书)、是否未过期,或尝试调整SSL版本(如context.options |= ssl.OP_NO_TLSv1_3,根据服务器支持情况修改);
  • 确认客户端证书的CN/SAN字段符合服务器的验证要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 19:13:26