如何使用Python requests库正确验证指定URL的SSL证书有效性?
问题根因
- 异常捕获逻辑错误:
requests开启verify=True时,SSL证书验证失败会抛出requests.exceptions.SSLError异常,该异常属于ConnectionError的子类,你没有单独捕获SSLError,导致证书验证失败的请求被归类到了连接错误分支,才输出了「无法解析主机」的错误提示。 - 证书错误判断逻辑完全无效:SSL验证失败时会直接中断请求抛出异常,根本不会返回response对象,你从response字符串中匹配错误信息的代码永远不会触发。
- 有效期校验逻辑脱离实际请求:你代码中的
commands、command.expirationDate和当前请求的站点证书没有任何关联,不管实际证书状态如何,这部分逻辑都会判定证书有效,这也是你朋友那边运行返回证书有效的直接原因。
修复后的实现代码
import requests import datetime import socket import urllib3 # 测试URL url = "https://expired.badssl.com/" try: response = requests.get(url, verify=True, allow_redirects=True, timeout=10) # 提取证书信息校验有效期 cert = response.raw.connection.sock.getpeercert() # 转换证书过期时间格式 expire_date = datetime.datetime.strptime(cert['notAfter'], "%b %d %H:%M:%S %Y %Z").date() current_date = datetime.date.today() if expire_date < current_date: print(f"url \"{url}\" has an expired SSL certificate") else: print(f"url \"{url}\" has a valid SSL certificate") except requests.exceptions.SSLError: print(f"url \"{url}\" has an invalid SSL certificate") except (requests.exceptions.InvalidURL, requests.exceptions.MissingSchema): print(f"Invalid url \"{url}\"") except (socket.gaierror, urllib3.exceptions.NewConnectionError, urllib3.exceptions.MaxRetryError, requests.exceptions.ConnectionError): print(f"Could not resolve url \"{url}\" to host") except Exception as e: print(f"Request error: {str(e)}")
关键修复说明
- 新增
requests.exceptions.SSLError捕获分支,且放在ConnectionError捕获之前,专门处理所有证书验证失败的场景,包括证书过期、自签名、域名不匹配等。 - 删除了无效的response字符串匹配逻辑,直接通过异常判断证书有效性。
- 替换了原有的无效有效期校验逻辑,直接从当前请求的连接中提取站点证书的实际过期时间进行校验。
- 增加了超时参数避免请求无限制挂起。
内容的提问来源于stack exchange,提问作者HullaBrian
相关产品推荐
相关产品推荐

