使用Python检测SSL证书有效性时遇getaddrinfo错误的咨询
错误解释与修复方案
错误含义
socket.gaierror: [Errno 11001] getaddrinfo failed 是域名解析失败错误:
getaddrinfo是系统负责将主机名(如www.google.com)转换为对应IP地址的核心函数- 你的代码中传入
ssl.get_server_certificate的是完整URL(https://www.google.com),而非纯主机名,导致该函数无法识别有效主机,触发DNS解析失败。
问题根源
ssl.get_server_certificate((url, 443)) 接收的第一个参数是(主机名, 端口),这里的主机名必须是不带http://或https://前缀的纯域名,你传入的完整URL被当作无效主机名,无法完成解析。
修复步骤及代码
1. 提取URL中的纯主机名
使用urllib.parse.urlparse解析URL,提取netloc部分作为主机名。
2. 替换私有解析函数(可选但推荐)
ssl._ssl._test_decode_cert是Python内部私有测试函数,兼容性差,建议改用cryptography库(需提前安装:pip install cryptography)进行证书解析。
3. 补充异常捕获
增加对域名解析失败等异常的处理,提升代码健壮性。
修复后的代码示例:
import requests import ssl import socket from datetime import datetime from urllib.parse import urlparse # 推荐使用cryptography库,需先安装 from cryptography import x509 from cryptography.hazmat.backends import default_backend def check_ssl_certificate(url): try: # 解析URL,提取纯主机名 parsed_url = urlparse(url) hostname = parsed_url.netloc if not hostname: print("无效的URL格式,请输入带协议的完整地址") return # 验证证书有效性并建立连接 response = requests.get(url, verify=True) # 获取服务器证书(使用纯主机名) cert_pem = ssl.get_server_certificate((hostname, 443)) # 使用cryptography解析证书(稳定可靠) cert_obj = x509.load_pem_x509_certificate(cert_pem.encode(), default_backend()) valid_from = cert_obj.not_valid_before_utc valid_to = cert_obj.not_valid_after_utc current_time = datetime.utcnow() if valid_from <= current_time <= valid_to: print("valid") else: print("invalid") except requests.exceptions.SSLError: print("无法获取或验证SSL证书") except socket.gaierror: print("域名解析失败,请检查URL格式或网络连接") except Exception as e: print(f"发生未知错误: {str(e)}") # 测试URL url = 'https://www.google.com' check_ssl_certificate(url)
额外说明
如果不想安装cryptography,也可以继续使用原有的证书解析逻辑,但必须确保传入ssl.get_server_certificate的是纯主机名,同时注意私有函数可能在Python版本更新后失效。
内容的提问来源于stack exchange,提问作者yushi
相关产品推荐
相关产品推荐

