ssl新闻资讯

文档中心

PythonSSL鏁板瓧璇佷功璇﹁В浠庡師鐞嗗埌瀹炴垬搴旂敤

时间 : 2025-09-27 16:30:16浏览量 : 4

什么是SSL数字证书?

2PythonSSL鏁板瓧璇佷功璇﹁В浠庡師鐞嗗埌瀹炴垬搴旂敤

想象一下你要给朋友寄一封重要的信,SSL数字证书就像是信封上的火漆印章,确保信件在传输过程中不被偷看或篡改。在互联网世界里,SSL(Secure Sockets Layer)数字证书就是网站的身份证明和安全通信的保障。

当你在浏览器地址栏看到那个小锁图标时,就表示你正在通过SSL/TLS加密通道与网站通信。Python作为广泛使用的编程语言,也提供了完善的SSL支持模块。

SSL证书的核心组成

一个标准的SSL证书包含三个关键部分:

1. 公钥:就像公开的电话号码,任何人都可以获取并使用它来加密数据

2. 私钥:就像你的私人密码,必须严格保密,用于解密数据

3. CA签名:由受信任的证书颁发机构(CA)提供的"担保",证明这个公钥确实属于声称的拥有者

举个例子:假设你要登录网上银行。银行服务器会发送它的SSL证书给你的浏览器。浏览器会检查:

- 这个证书是否由可信CA签发(比如VeriSign、Let's Encrypt)

- 证书中的域名是否与你访问的网站一致

- 证书是否在有效期内

Python中的SSL模块基础用法

Python内置的`ssl`模块让我们可以轻松处理SSL连接。下面是一个最简单的HTTPS请求示例:

```python

import ssl

import urllib.request

context = ssl.create_default_context()

response = urllib.request.urlopen("https://example.com", context=context)

print(response.read())

```

这段代码创建了一个默认的SSL上下文,然后用它安全地获取网页内容。`create_default_context()`会自动加载系统信任的根证书。

常见问题与解决方案

1. 自签名证书问题

很多内部系统使用自签名证书(自己充当CA签发的证书),Python默认不信任这类证书:

错误示例 - 会抛出ssl.SSLError

response = urllib.request.urlopen("https://internal-server")

解决方案有三种:

方案A:关闭验证(不推荐)

context = ssl._create_unverified_context()

方案B:添加自定义CA

context = ssl.create_default_context(cafile="my_custom_ca.pem")

方案C:添加单个证书信任

context.load_verify_locations(cafile="server_cert.pem")

2. 主机名验证失败

有时会遇到"hostname doesn't match"错误:

server_cert.pem是发给foo.example.com的,但我们访问的是bar.example.com

response = urllib.request.urlopen("https://bar.example.com", context=context)

解决方案是禁用主机名检查(仅限测试环境):

context.check_hostname = False

3. TLS版本过时问题

老系统可能只支持TLS1.0/1.1等不安全协议:

强制使用现代安全协议 (Python 3.7+)

context.minimum_version = ssl.TLSVersion.TLSv1_2

Python生成自签名证书实战

开发测试时经常需要自签名证书。下面用Python生成一个:

from cryptography import x509

from cryptography.x509.oid import NameOID

from cryptography.hazmat.primitives import hashes, serialization

from cryptography.hazmat.primitives.asymmetric import rsa

import datetime

生成私钥

private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)

创建自签名证书的主体信息(Subject)

subject = x509.Name([

x509.NameAttribute(NameOID.COUNTRY_NAME, "CN"),

x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Beijing"),

x509.NameAttribute(NameOID.LOCALITY_NAME, "Beijing"),

x509.NameAttribute(NameOID.ORGANIZATION_NAME, "My Company"),

x509.NameAttribute(NameOID.COMMON_NAME, "mysite.example.com"),

])

设置有效期(通常1年)

cert = x509.CertificateBuilder().subject_name(

subject).issuer_name(

subject).public_key(

private_key.public_key()

).serial_number(

x509.random_serial_number()

).not_valid_before(

datetime.datetime.now(datetime.timezone.utc)

).not_valid_after(

datetime.datetime.now(datetime.timezone.utc) + datetime.timedelta(days=365)

).add_extension(

x509.SubjectAlternativeName([x509.DNSName("localhost")]),

critical=False,

).sign(private_key, hashes.SHA256())

保存私钥和证书到文件(PEM格式)

with open("private_key.pem", "wb") as f:

f.write(private_key.private_bytes(

encoding=serialization.Encoding.PEM,

format=serialization.PrivateFormat.TraditionalOpenSSL,

encryption_algorithm=serialization.NoEncryption(),

))

with open("certificate.pem", "wb") as f:

f.write(cert.public_bytes(serialization.Encoding.PEM))

Flask/Django HTTPS服务配置示例

有了私钥和证书后,我们可以配置Web服务使用HTTPS:

Flask配置示例:

from flask import Flask

app = Flask(__name__)

@app.route("/")

def hello():

return "Hello HTTPS World!"

if __name__ == "__main__":

app.run(ssl_context=('certificate.pem', 'private_key.pem'))

Django配置示例:

在settings.py中添加:

SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

SECURE_SSL_REDIRECT = True

SESSION_COOKIE_SECURE = True

CSRF_COOKIE_SECURE = True

Python检查远程服务器SSL信息

我们可以用Python编写工具检查远程服务器的SSL配置情况:

import socket

import ssl

from pprint import pprint

def check_ssl(hostname, port=443):

context = ssl.create_default_context()

with socket.create_connection((hostname, port)) as sock:

with context.wrap_socket(sock, server_hostname=hostname) as ssock:

cert_info = ssock.getpeercert()

cipher_info = ssock.cipher()

print(f"\n=== {hostname} SSL信息 ===")

print("\n[版本信息]")

print(f"协议版本: {ssock.version()}")

print("\n[加密套件]")

print(f"正在使用的加密算法: {cipher_info[0]}")

print("\n[有效期]")

pprint(cert_info['notBefore'])

pprint(cert_info['notAfter'])

print("\n[主题信息]")

for field in cert_info['subject']:

for k,v in field:

print(f"{k}: {v}")

check_ssl("www.baidu.com")

check_ssl("github.com")

这个脚本可以输出目标网站的:

- SSL/TLS协议版本(TLS1.2/1.3等)

- 正在使用的加密算法套件(AES256-GCM-SHA384等)

- 证书的有效期和主体信息(公司名称、域名等)

Python处理客户端认证(mTLS)

在一些高安全要求的场景中,服务器也会验证客户端的身份——这就是双向TLS认证(mTLS)。比如银行API接口通常要求客户端提供自己的数字证书。

服务端代码示例:

```python

HOST, PORT = '0.0.0.0', 8443

SSL上下文配置 - require client cert!

context_server = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)

context_server.load_cert_chain('server.crt', 'server.key')

context_server.load_verify_locations('ca.crt')

context_server.verify_mode = ssl.CERT_REQUIRED

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:

sock.bind((HOST,PORT))

sock.listen()

with context_server.wrap_socket(sock, server_side=True) as ssock:

conn,_addr_client=ssock.accept()

data_client=conn.read()

conn.write(b"Hello mTLS client!")

conn.close()

客户端代码示例:

import socket

import ssl

HOST,PORT='localhost',8443

Client context with cert chain

context_client=ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)

context_client.load_cert_chain('client.crt','client.key')

context_client.load_verify_locations('ca.crt')

with socket.socket(socket.AF_INET,socket.SOCK_STREAM)as sock:

with context_client.wrap_socket(sock,

server_hostname='myserver.local')as ssock:

ssock.connect((HOST,PORT))

ssock.send(b"Hello mTLS world!")

response_data=str(ssock.read(),'utf-8')

print(f"Server response:{response_data}")

这种mTLS模式确保了双方都经过严格身份验证后才能建立连接。

Python中常见的SSLError及解决思路

在使用Python进行HTTPS通信时可能会遇到各种SSLError错误码:

| 错误码 | 常见原因 | 解决方案建议 |

||--||

| CERTIFICATE VERIFY FAILED | CA根不受信任/过期/吊销 | `create_unverified_context()`临时绕过或安装正确CA |

| UNKNOWN CA | CA不在系统信任库中 | `load verify locations()`加载自定义CA |

| HOSTNAME MISMATCH | CN/SAN不匹配实际域名 | `check hostname=False`或修正DNS |

| SSLV3 ALERT HANDSHAKE FAILURE | TLS版本不兼容 | `minimum version=TLSv1\_2`强制升级 |

| DH KEY TOO SMALL | DH参数太弱(<2048bit) | `OP SINGLE DH USE`或更新密钥 |

例如处理过时的金融系统接口可能需要特殊配置:

``` python

legacy ctx=ssl SSLContext(protocol PROTOCOL TLS CLIENT)

旧版协议兼容模式

legacy ctx set ciphers('DES CBC3 SHA:AES128 SHA256')

指定老旧算法套件

legacy ctx verify mode=CERT OPTIONAL

放宽验证要求

try requests get(url=https legacybank com api balance verify='/path/to/legacy ca pem')

except SSLError as e: logger warning(f'Handshake failed:{e} retrying...')

这种场景下需要在安全性和兼容性之间做出权衡决策。

通过以上内容我们可以看到,Python提供了强大而灵活的SSL/TLS支持能力。无论是开发安全的客户端程序、构建HTTPS服务还是进行安全测试分析都能找到合适的工具方法。理解这些原理和技术细节将帮助开发者构建更加安全的网络应用系统。

TAG:python ssl 数字证书,python项目的ssl证书怎么配,python ssl认证,python ssl模块详解