如何让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
相关产品推荐
相关产品推荐

