文档中心
Python涓嬭浇绔欑偣SSL璇佷功鍏ㄦ敾鐣ヤ粠鍘熺悊鍒板疄鎴樹唬鐮佺ず渚?txt
时间 : 2025-09-27 16:30:20浏览量 : 1

SSL证书是保障网站数据传输安全的核心要素,对于Python开发者来说,掌握如何通过代码下载和分析SSL证书是一项实用技能。本文将带你深入理解SSL证书的工作原理,并通过多个Python代码示例展示如何从任意网站获取SSL证书信息。
一、SSL证书基础:网站的"身份证"
想象一下SSL证书就像是网站的身份证。当你在浏览器访问https://开头的网站时,浏览器会先检查这个"身份证"是否真实有效。这张"身份证"包含三个关键信息:
1. 网站身份信息:就像身份证上有你的姓名和照片一样,SSL证书包含网站的域名、公司名称等信息
2. 颁发机构:如同公安局签发你的身份证,SSL证书由受信任的CA机构(如Let's Encrypt、DigiCert)签发
3. 有效期:和身份证一样有使用期限
举个例子,当你访问https://github.com时:
- 浏览器会收到GitHub服务器的SSL证书
- 检查是否由可信CA签发
- 核对证书中的域名是否匹配
- 确认证书在有效期内
只有全部验证通过,才会建立安全连接。否则你会看到类似"您的连接不是私密连接"的警告。
二、Python获取SSL证书的4种方法
方法1:使用ssl模块获取原始证书
```python
import ssl
import socket
from pprint import pprint
def get_ssl_cert(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:
cert = ssock.getpeercert()
return cert
示例:获取GitHub的SSL证书
cert_info = get_ssl_cert("github.com")
pprint(cert_info)
```
这段代码会输出类似这样的信息:
{'issuer': ((('countryName', 'US'),),
(('organizationName', 'DigiCert Inc'),),
(('organizationalUnitName', 'www.digicert.com'),),
(('commonName', 'DigiCert SHA2 High Assurance Server CA'),)),
'notAfter': 'Mar 8 12:00:00 2025 GMT',
'notBefore': 'Mar 5 00:00:00 2025 GMT',
'serialNumber': '0E2E4B0CFFA9B1B5D5F7D3A0E9F8B7D2',
...}
方法2:使用requests库简化流程
import requests
from ssl import SSLContext
def get_cert_via_requests(url):
response = requests.get(url, verify=True)
cert = response.connection.sock.getpeercert()
示例用法
cert = get_cert_via_requests("https://python.org")
print(f"Python官网证书有效期至: {cert['notAfter']}")
方法3:保存PEM格式的完整证书链
有时我们需要将整个证书链保存为文件进行分析:
def save_full_cert_chain(hostname, filename="certificate.pem"):
cert_pem = ssl.get_server_certificate((hostname, 443))
with open(filename, "w") as f:
f.write(cert_pem)
print(f"已保存 {hostname} 的完整证书到 {filename}")
保存百度首页的SSL证书
save_full_cert_chain("www.baidu.com", "baidu_cert.pem")
方法4:高级应用 - OpenSSL命令行集成
对于需要更深度分析的情况,可以结合OpenSSL命令行工具:
import subprocess
def check_cert_with_openssl(hostname):
cmd = f"openssl s_client -connect {hostname}:443 -showcerts
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode == 0:
print(result.stdout)
else:
print("执行出错:", result.stderr)
OpenSSL方式检查淘宝网证书链
check_cert_with_openssl("www.taobao.com")
三、实战案例解析:验证电商网站安全性
假设我们要开发一个监控电商网站安全性的脚本:
from datetime import datetime
def check_ecommerce_site(domain):
try:
cert = get_ssl_cert(domain)
SSL有效期检查(剩余天数)
expiry_date = datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z')
days_left = (expiry_date - datetime.now()).days
HTTPS配置评分(满分100)
score = min(days_left * (1 if days_left >30 else -1),
100 if len(cert.get('subjectAltName', [])) >0 else
(80 if "CN=" in str(cert['subject']) else
60))
print(f"{domain}安全检查结果:")
print(f"- SSL剩余有效期: {days_left}天")
print(f"- HTTPS配置评分: {score}/100")
if days_left <15:
print("??警告: SSL即将过期!")
except Exception as e:
print(f"{domain}检测失败:", str(e))
JD.COM的安全检查
check_ecommerce_site("www.jd.com")
输出可能类似于:
www.jd.com安全检查结果:
- SSL剩余有效期: 87天
- HTTPS配置评分: 87/100
四、常见问题与解决方案(Q&A)
Q1: Python下载的SSL信息和浏览器看到的不一致?
A: Python默认只验证服务器发送的第一个终端实体(end-entity)证书。要获取完整链需要额外处理:
```python
def get_full_chain(hostname):
context = ssl.SSLContext()
conn = context.wrap_socket(socket.socket(), server_hostname=hostname)
conn.connect((hostname,443))
DER格式转为PEM格式
pem_data = []
for der in conn.getpeercert(binary_form=True) or []:
pem_data.append(
"--BEGIN CERTIFICATE--\n" +
"\n".join(textwrap.wrap(base64.b64encode(der).decode(),64)) +
"\n--END CERTIFICATE--\n"
)
return pem_data
finally:
conn.close()
chain_jd = get_full_chain("www.jd.com")[0]
JD根CA通常是第一个
Q2: Python报错`ssl.SSLCertVerificationError`怎么处理?
这通常意味着:
1. CA根不在系统信任库中(自签名或内部CA)
2. CN/SAN不匹配当前域名
临时解决方案(仅限测试环境):
context.verify_mode = ssl.CERT_NONE
??禁用验证(不安全)
生产环境正确做法是添加自定义CA包:
context.load_verify_locations("/path/to/custom/ca-bundle.crt")
五、进阶技巧与最佳实践
TLS指纹识别技术
某些安全设备会通过TLS握手特征识别客户端类型:
def spoof_firefox_tls():
ctx = ssl.SSLContext()
ctx.set_alpn_protocols(["h2", "http/1.1"])
Firefox支持的ALPN协议
ctx.options |= (
ssl.PROTOCOL_TLS |
TLSv1+协议族
ssl.PROTOCOL_TLSv1 |
TLSv1.x兼容性
ssl.PROTOCOL_TLSv1_2
Firefox默认TLS版本
)
ciphers="TLS_AES...CHACHA..."
Firefox特有密码套件列表
ctx.set_ciphers(ciphers)
return ctx
with requests.Session() as sess:
sess.mount("https://", MyAdapter(ctx))
HTTP请求时模拟Firefox指纹
OCSP装订状态检查
在线验证吊销状态比CRL更高效:
from cryptography.x509 import ocsp
async def check_revocation(url):
builder = ocsp.OCSPRequestBuilder()
builder.add_by_url(url)
req_bytes=builder.build().public_bytes(...)
async with aiohttp.ClientSession() as sess:
resp=await sess.post(
"http://ocsp.digicert.com",
data=req_bytes,
headers={"Content-Type":"application/ocsp-request"}
)
return ocsp.load_response(resp.content).status == ocsp.VALID
```
> 专业提示:生产环境中建议使用`pyOpenSSL`或`cryptography`等专业库替代标准库ssl模块,它们提供更完整的X509处理能力。
六、与资源推荐
本文介绍的技术可应用于以下场景:
?自动化HTTPS监控系统开发
?爬虫绕过WAF指纹检测
?企业内部PKI管理工具开发
扩展学习资源推荐:
??《Bulletproof SSL and TLS》(Ivan Risti?著) - SSL/TLS圣经级著作
?? Let's Encrypt文档 - https://letsencrypt.org/docs/
TAG:python下载站点ssl证书,python网站下载,the ssl module in python is,python中的ssl模块不能用,python ssl certificate,python下载链接