文档中心
PythonSSL璇佷功瑙f瀽瀹炴垬浠庡師鐞嗗埌浠g爜瀹炵幇
时间 : 2025-09-27 16:30:18浏览量 : 2
SSL证书基础概念

SSL/TLS证书是互联网安全通信的基石,它就像网站的"身份证"。当你在浏览器地址栏看到那个小锁图标时,说明当前连接使用了SSL加密。让我们用一个生活中的例子来理解:
想象你要给朋友寄一封重要信件。普通HTTP就像用明信片寄送 - 任何人都能看到内容。而HTTPS(HTTP+SSL)则像是把信放进保险箱,只有你和朋友有钥匙能打开。
SSL证书主要包含以下关键信息:
- 颁发给谁(Common Name):比如www.example.com
- 颁发者(Issuer):如Let's Encrypt、DigiCert等CA机构
- 有效期:证书不是永久有效的
- 公钥:用于加密通信的密钥对中的公开部分
Python中的SSL模块
Python内置的ssl模块提供了丰富的SSL/TLS功能。我们先来看一个最简单的例子 - 获取网站证书:
```python
import ssl
import socket
def get_certificate(hostname, port=443):
"""获取远程服务器SSL证书"""
context = ssl.create_default_context()
with socket.create_connection((hostname, port)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
return ssock.getpeercert()
示例:获取百度的证书信息
cert_info = get_certificate("www.baidu.com")
print(cert_info)
```
运行这段代码,你会看到一个包含百度SSL证书信息的字典。但输出的内容可能看起来有些杂乱,我们需要进一步解析。
深入解析证书内容
让我们改进上面的代码,提取更有价值的信息:
from datetime import datetime
def parse_certificate(cert):
"""解析证书信息"""
print("颁发给:", cert.get('subject'))
print("颁发者:", cert.get('issuer'))
处理有效期
not_before = datetime.strptime(cert['notBefore'], '%b %d %H:%M:%S %Y %Z')
not_after = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
print(f"有效期: {not_before} 至 {not_after}")
SANs(主题备用名称)
for extension in cert.get('subjectAltName', []):
print(f"备用名称: {extension[0]} - {extension[1]}")
使用之前的函数获取证书后解析
parse_certificate(cert_info)
这个改进版本会输出更结构化的信息。你可能注意到有些字段如'subject'和'issuer'还是不太易读,因为它们是以元组列表的形式存储的。
处理X.509证书格式
实际上,Python返回的是已经解码的证书信息。如果要直接处理原始X.509证书,我们可以使用cryptography库:
from cryptography import x509
from cryptography.hazmat.backends import default_backend
def parse_x509_certificate(pem_data):
"""解析X.509格式证书"""
cert = x509.load_pem_x509_certificate(pem_data, default_backend())
print("版本:", cert.version)
print("序列号:", cert.serial_number)
subject = cert.subject
print("\n主题信息:")
for attr in subject:
print(f"{attr.oid._name}: {attr.value}")
issuer = cert.issuer
print("\n颁发者信息:")
for attr in issuer:
print("\n有效期:")
print(f"生效时间: {cert.not_valid_before}")
print(f"过期时间: {cert.not_valid_after}")
print("\n扩展信息:")
for ext in cert.extensions:
if ext.oid.dotted_string == '2.5.29.17':
SAN扩展
names = ext.value.get_values_for_type(x509.DNSName)
print("SANs:", ", ".join(names))
SSL验证的重要性
在实际应用中,仅仅获取证书是不够的,验证其有效性才是关键。Python默认会验证主机名和信任链:
def verify_certificate(hostname):
context = ssl.create_default_context()
try:
with socket.create_connection((hostname, 443)) as sock:
with context.wrap_socket(sock, server_hostname=hostname) as ssock:
cert = ssock.getpeercert()
return True, "验证通过"
except ssl.CertificateError as e:
return False, f"证书错误: {e}"
except ssl.SSLError as e:
return False, f"SSL错误: {e}"
常见的验证失败原因包括:
1. 自签名证书(没有受信任的CA签发)
2. 主机名不匹配(访问example.com但证书是给*.example.org的)
3. 过期或未生效的证书
4. CA根证书不在系统信任库中
OpenSSL命令行对比
熟悉OpenSSL命令行的同学可能会问:Python实现和OpenSSL命令有什么区别?让我们对比一下:
OpenSSL方式:
openssl s_client -connect www.example.com:443 -showcerts
Python方式的优势:
1. 可编程性:可以集成到自动化工具中
2. 灵活性:可以自定义验证逻辑和处理流程
3. 跨平台:不需要依赖系统OpenSSL版本
PyOpenSSL高级用法
对于更高级的需求,PyOpenSSL提供了更多功能:
from OpenSSL import SSL, crypto
def check_crl(cert_pem):
"""检查CRL(吊销列表)"""
cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert_pem)
x509 = X509.load_cert_string(cert_pem)
TODO: CRL检查逻辑...
return True
def verify_ocsp(cert_pem):
"""OCSP在线状态检查"""
TODO: OCSP检查逻辑...
这些高级检查可以帮助发现已被吊销但未过期的可疑证书。
HTTPS请求时的注意事项
在使用requests等库发起HTTPS请求时,了解背后的SSL验证很重要:
import requests
??危险示范(禁用验证)
requests.get('https://expired.badssl.com', verify=False)
?正确做法(自定义CA包)
requests.get('https://example.com', verify='/path/to/custom/ca-bundle.crt')
?另一种正确做法(严格主机名验证)
session = requests.Session()
session.mount('https://', requests.adapters.HTTPAdapter(
max_retries=3,
assert_hostname=True,
assert_fingerprint='sha256指纹...'
))
在生产环境中禁用verify=False是非常危险的中间人攻击漏洞!
SSL/TLS最佳实践
1. 定期检查:监控所有服务的到期时间(可以用我们写的脚本自动化)
2. 最小权限:私钥文件应设置严格的访问权限
3. 及时更新:关注TLS协议漏洞(如POODLE、Heartbleed)
4. 强化配置:禁用老旧协议和弱密码套件
以下是一个简单的到期监控脚本示例:
```python
import smtplib
from email.mime.text import MIMEText
def check_expiry_and_alert(domains):
for domain in domains:
certs_left_days = (cert['notAfter'] - datetime.now()).days
if certs_left_days < threshold_days:
send_expiry_alert(domain)
def send_expiry_alert(domain):
msg_text = f"{domain} SSL将在{certs_left_days}天后过期!"
try:
smtp.sendmail(from_addr="monitor@example.com", to_addrs=["admin@example.com"], msg=msg_text.as_string())
except Exception as e:
logging.error(f"邮件发送失败:{e}")
if __name__ == '__main__':
tracked_domains = ["www.example.com", "api.example.com"]
while True:
check_expiry_and_alert(tracked_domains)
time.sleep(86400)
每天检查一次
通过本文的学习,你应该已经掌握了使用Python处理和解析SSL/TLS的核心技能。记住在实际应用中要特别注意安全性问题!
TAG:python ssl 证书 解析,python3 ssl,python ssl module,pythonssl证书验证错误,python项目的ssl证书怎么配

