我正在使用Python 2.7.13(Win x64)脚本来验证SSL证书,并提醒问题。但是,我遇到的问题是,只有在证书有效的情况下,脚本才会返回信息。
如果证书无效,我会收到CERTIFICATE_VERIFY_FAILED SSL错误。通常我只是在引发错误时使用try / catch并且只是警告证书无效,但问题是我需要证书过期的实际日期。
Per https://docs.python.org/2/library/ssl.html我尝试使用conn._https_verify_certificates(enable = False)来禁用证书验证,但是收到属性_https_verify_certificates不存在的错误。
到目前为止,这是我的代码。我确定我错过了一些明显的东西。当然,Python可以在不验证的情况下提取SSL证书,对吗?
import socket
import ssl
def ssl_expiry_datetime(hostname):
ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z'
context = ssl.create_default_context()
conn = context.wrap_socket(
socket.socket(socket.AF_INET),
server_hostname=hostname,
)
# 3 second timeout because Lambda has runtime limitations
conn.settimeout(3.0)
#conn._https_verify_certificates(enable=False)
conn.connect((hostname, 443))
ssl_info = conn.getpeercert()
# parse the string from the certificate into a Python datetime object
return ['notAfter']
myhost = 'www.google.com'
print ssl_expiry_datetime(myhost)
非常感谢!!!!
答案 0 :(得分:1)
经过大量的反复试验后,我发现您可以使用check_hostname功能关闭SSLcertificate主机名验证。
context.check_hostname = False
如果目标与SSL证书上的公用名(CN)不匹配,这将允许您的程序在Web服务器上进行连接。但是,当Web服务器使用无效的SSL证书时,连接将失败并引发ConnetionError错误。 如果目标是获取所有SSL证书,即使是无效的证书,以下解决方案也只能部分满足您的需求。
这是一个建议的解决方案:
import socket, ssl
def ssl_expiry_datetime(hostname):
ssl_date_fmt = r'%b %d %H:%M:%S %Y %Z'
context = ssl.create_default_context()
context.check_hostname = False
conn = context.wrap_socket(
socket.socket(socket.AF_INET),
server_hostname=hostname,
)
# 3 second timeout because Lambda has runtime limitations
conn.settimeout(3.0)
#conn._https_verify_certificates(enable=False)
conn.connect((hostname, 443))
ssl_info = conn.getpeercert()
# parse the string from the certificate into a Python datetime object
return ['notAfter']
myhost = 'example.com'
print ssl_expiry_datetime(myhost)
或者,您可以使用requests库,它可以让您完全关闭验证。
<强>参考文献:强>