你好,我正在使用Python库Websockets。在开发过程中一切正常,但在服务器上它会崩溃,因为需要使用WSS。上面的链接给出了一个示例来说明如何做到这一点:
#!/usr/bin/env python
# WSS (WS over TLS) server example, with a self-signed certificate
import asyncio
import pathlib
import ssl
import websockets
async def hello(websocket, path):
name = await websocket.recv()
print(f"< {name}")
greeting = f"Hello {name}!"
await websocket.send(greeting)
print(f"> {greeting}")
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
localhost_pem = pathlib.Path(__file__).with_name("localhost.pem")
ssl_context.load_cert_chain(localhost_pem)
start_server = websockets.serve(
hello, "localhost", 8765, ssl=ssl_context
)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
这段代码很简单,但我不知道如何生成它所需的文件(服务器和客户端都需要)。我已经尝试了“创建PEM文件”,但没有结果,并且收到了各种各样的SSL错误。请有人能够解释一下如何为该应用程序创建PEM文件吗?谢谢。
编辑: 根据答案,我使用了……
sudo openssl req -newkey rsa:2048 -new -nodes -x509 -days 3650 -keyout key.pem -out cert.pem
这样做会创建两个文件。
我现在成功地通过执行以下操作使服务器监听:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
path_key = pathlib.Path(__file__).with_name("key.pem")
ssl_context.load_cert_chain(path_cert, keyfile=path_key)
print("Listening for connection...")
start_server = websockets.serve(handler, HOSTNAME, PORT, ssl=ssl_context)
我唯一还遇到问题的部分是让客户端连接,我尝试了以下代码:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
ssl_context.load_cert_chain(path_cert)
async with websockets.connect(uri, ssl=ssl_context) as websocket:
但我收到了以下错误信息:ssl.SSLError: [SSL] PEM lib (_ssl.c:3854)
我还尝试过:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
path_key = pathlib.Path(__file__).with_name("key.pem")
ssl_context.load_cert_chain(path_cert, keyfile=path_key)
async with websockets.connect(uri, ssl=ssl_context) as websocket:
并且收到了错误消息:ssl.SSLCertVerificationError: [SSL:CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1076)
编辑2: 根据答案,我尝试为客户端执行以下操作:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.load_verify_locations()
async with websockets.connect(uri, ssl=ssl_context) as websocket:
这会生成一个新的错误:
TypeError: cafile、capath 和 cadata 不能全部省略
尝试第二个建议:ssl_context = ssl.create_default_context()
ssl_context.load_verify_locations(certifi.where())
async with websockets.connect(uri, ssl=ssl_context) as websocket:
生成错误:ssl.SSLCertVerificationError:[SSL:CERTIFICATE_VERIFY_FAILED]证书验证失败:自签名证书(_ssl.c:1076)
编辑3: 最终工作客户端:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
path_cert = pathlib.Path(__file__).with_name("cert.pem")
ssl_context.load_verify_locations(path_cert)
async with websockets.connect(uri, ssl=ssl_context) as websocket: