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

如何让Python信任服务器自签名TLS证书?遇ssl.SSLError报错

我懂你这种折腾半天没解决的糟心——在Windows上用Python3.6.5连接带自签名证书的服务器,碰到ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:833),而且试过把证书内容加到cacert.pem里还是没用,对吧?给你几个针对性的解决办法,亲测有效:

1. 直接在代码里指定自定义证书路径

有时候Python3.6可能没正确识别你修改的默认cacert.pem,或者你加证书的位置不对。不如跳过默认CA存储,直接在代码里指定你的自签名证书文件:

如果你用requests库,代码可以这么写:

import ssl
import requests

# 替换成你的自签名证书.pem文件的绝对路径
custom_cert = r"C:\Users\YourName\server-cert.pem"

try:
    resp = requests.get("https://your-server-domain:port", verify=custom_cert)
    print("连接成功!响应内容:", resp.text[:100])
except ssl.SSLError as e:
    print(f"SSL错误详情: {e}")

如果用原生socket和ssl模块,这么写更底层:

import socket
import ssl

cert_path = r"C:\Users\YourName\server-cert.pem"
# 创建带自定义CA的SSL上下文
context = ssl.create_default_context(cafile=cert_path)

with socket.create_connection(("your-server-domain", 443)) as sock:
    with context.wrap_socket(sock, server_hostname="your-server-domain") as ssl_sock:
        print("SSL连接已建立")
        print("服务器证书信息:", ssl_sock.getpeercert())
        # 发送请求示例
        ssl_sock.sendall(b"GET / HTTP/1.1\r\nHost: your-server-domain\r\n\r\n")
        print("响应内容:", ssl_sock.recv(1024).decode())
2. 检查证书格式和cacert.pem的修改位置

你说把证书内容加到cacert.pem里没效果,大概率是这两个问题:

  • 证书格式不对:确保你的自签名证书是完整的PEM格式——必须包含-----BEGIN CERTIFICATE-----和-----END CERTIFICATE-----首尾标记,中间是连续的Base64编码内容,不能有多余的空行或乱码。
  • 修改错了文件:Python3.6在Windows上,如果用requests库,它默认用certifi包的cacert.pem,路径一般是C:\Python36\Lib\site-packages\certifi\cacert.pem。你要修改的是这个文件,而不是系统或其他地方的CA证书存储。
3. 临时绕过验证(仅测试用!)

如果你只是临时调试,不想纠结证书配置,可以关闭SSL验证,但绝对不要在生产环境这么做,这会完全暴露你的连接在安全风险下:

import requests
import urllib3

# 屏蔽不安全请求的警告
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# 关闭SSL验证
resp = requests.get("https://your-server-domain:port", verify=False)
print(resp.text)

用原生ssl模块的话:

import socket
import ssl

# 创建不验证证书的上下文
context = ssl._create_unverified_context()

with socket.create_connection(("your-server-domain", 443)) as sock:
    with context.wrap_socket(sock, server_hostname="your-server-domain") as ssl_sock:
        print("跳过验证的SSL连接已建立")
4. 检查证书的SAN字段是否正确

Python3.6的SSL验证会严格检查证书的**Subject Alternative Name(SAN)**字段,即使证书的CN(通用名称)和服务器域名匹配,如果没有配置SAN,也会验证失败。

你可以用OpenSSL工具查看证书的SAN字段(如果没装OpenSSL,可以下载轻量版本):

openssl x509 -in server-cert.pem -text -noout

在输出里找X509v3 Subject Alternative Name这一项,如果没有的话,需要重新生成带SAN的自签名证书。比如先写一个配置文件san.ini:

[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_ca
prompt = no

[req_distinguished_name]
CN = your-server-domain

[v3_ca]
subjectAltName = DNS:your-server-domain, IP:192.168.1.100  # 替换成你的域名或IP

然后用命令生成证书:

openssl req -x509 -newkey rsa:4096 -keyout server-key.pem -out server-cert.pem -days 365 -config san.ini -nodes

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 09:04:12