gpt4 book ai didi

python - flask-socketio 服务器和 python-socketio 之间的安全通信

转载 作者:太空宇宙 更新时间:2023-11-03 13:58:13 27 4
gpt4 key购买 nike

我正在使用 flask-socketio 和 python-socketio 开发一个项目。为了确保通信安全,系统需要使用 SSL 进行升级。我正在使用 Mac 和 Python 3.7。

我使用 openssl (rootCA.pem) 创建了一个证书并将其添加到 Mac 的钥匙串(keychain)中。之后,我使用 rootCA.pem 发布了 server.certserver.key。我使用 flask-socketio 构建了 Web 服务器,在其一侧添加了 server.certserver.key。最后,该网站与 ssl 配合良好。

当我想保护 flask-socketio 服务器和 python-socketio 客户端之间的通信时,问题发生了。当客户端尝试连接服务器时,连接被拒绝并引发未知错误:

ssl.SSLError: [SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:2488)

我做了一些研究,意识到这个问题可能是由于 Python 3.7 使用了它自己的 OpenSSL 私有(private)副本。因此,SocketIO 客户端无法验证我的自签名证书。这是来自 Python 3.7 安装的信息:

This variant of Python 3.7 includes its own private copy of OpenSSL 1.1.1. The deprecated Apple-supplied OpenSSL libraries are no longer used. This means that the trust certificates in system and user keychains managed by the Keychain Access application and the security command line utility are no longer used as defaults by the Python ssl module. A sample command script is included in /Applications/Python 3.7 to install a curated bundle of default root certificates from the third-party certifi package (https://pypi.org/project/certifi/). If you choose to use certifi, you should consider subscribing to the project's email update service to be notified when the certificate bundle is updated.

所以我转到/Applications/Python 3.7 文件夹并执行Install Certificates.command

不过,这不是问题的关键。因为 python certifi 是一个精心策划的根证书集合。当然,它不包含我的自签名证书。所以,为了解决这个问题,我需要让 Python 找到 rootCA.pem

在python certifi的文件夹下,有一个名为cacert.pem的文件。这包含根证书。所以我在cacert.pem的最后添加了rootCA.pem的内容。

之后,我在命令行中尝试了这段代码:

openssl verify -CAfile cacert.pem server.crt

输出:

server.crt: OK

我认为,在这种情况下,cacert.pem 可以验证服务器的证书。我知道这不是一个优雅的解决方案。如果您有更好的方法让 python 找到我的自签名证书,请告诉我。

之后,我尝试使用 python-socketio 连接到 flask-socketio 服务器。这一次,我又犯了一个错误。在服务器端,日志信息为:

(57183) accepted ('127.0.0.1', 56322)
0fd838477c534dfda802bfb0d130d358: Sending packet OPEN data {'sid': '0fd838477c534dfda802bfb0d130d358', 'upgrades': ['websocket'], 'pingTimeout': 60000, 'pingInterval': 25000}
0fd838477c534dfda802bfb0d130d358: Sending packet MESSAGE data 0
127.0.0.1 - - [10/Oct/2019 08:50:36] "GET /socket.io/?transport=polling&EIO=3&t=1570706436.665149 HTTP/1.1" 200 349 0.000436
(57183) accepted ('127.0.0.1', 56324)
http://localhost:3000 is not an accepted origin.
127.0.0.1 - - [10/Oct/2019 08:50:36] "GET /socket.io/?transport=websocket&EIO=3&sid=0fd838477c534dfda802bfb0d130d358&t=1570706436.685631 HTTP/1.1" 400 122 0.000182

而在客户端,错误是这样抛出的:

Traceback (most recent call last):
File "simple_client.py", line 18, in <module>
sio.connect('https://localhost:3000', namespaces="/channel_A")
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/socketio/client.py", line 262, in connect
engineio_path=socketio_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/engineio/client.py", line 170, in connect
url, headers, engineio_path)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/engineio/client.py", line 308, in _connect_polling
if self._connect_websocket(url, headers, engineio_path):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/engineio/client.py", line 346, in _connect_websocket
cookie=cookies)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websocket/_core.py", line 514, in create_connection
websock.connect(url, **options)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websocket/_core.py", line 226, in connect
self.handshake_response = handshake(self.sock, *addrs, **options)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websocket/_handshake.py", line 79, in handshake
status, resp = _get_resp_headers(sock)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/websocket/_handshake.py", line 160, in _get_resp_headers
raise WebSocketBadStatusException("Handshake status %d %s", status, status_message, resp_headers)
websocket._exceptions.WebSocketBadStatusException: Handshake status 400 BAD REQUEST

我不知道为什么会这样。 flask-socketio 服务器和 python-socketio 客户端之间的通信在没有 SSL 的情况下也能正常工作。所以我认为代码可能没有什么问题,但我还是在这里给出了代码。这是针对服务器的:

from flask import Flask, render_template
from flask_socketio import SocketIO
from flask_socketio import Namespace
import eventlet

app = Flask(__name__, template_folder="templates")

app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, engineio_logger=True, logger=True)

# Create a URL route in our application for "/"
@app.route('/')
def home():
"""
This function loads the homepage
"""
return render_template('index.html')


class MyCustomNamespace(Namespace):
def on_connect(self):
print("Client just connected")

def on_disconnect(self):
print("Client just left")

def on_messages(self, data):
print(f"\nReceived data from client: \n {data}\n")
return data

socketio.on_namespace(MyCustomNamespace('/channel_A'))

if __name__ == "__main__":
eventlet.wsgi.server(
eventlet.wrap_ssl(eventlet.listen(("localhost", 3000)),
certfile='server.crt',
keyfile='server.key',
server_side=True), app)
# socketio.run(app, host="localhost", port=3000, debug=True)

这是给客户的:

import socketio

sio = socketio.Client()

def message_received(data):
print(f"Message {data} received")

@sio.on('connect', namespace="/channel_A")
def on_connect():
print("Connect...")

@sio.on('disconnect', namespace="/channel_A")
def on_disconnect():
print(f"Disconnected from server")

sio.connect('https://localhost:3000', namespaces="/channel_A")

求助!我知道我的问题很啰嗦。但我只想展示我尝试解决问题的方式。如果有任何问题,请告诉我。谢谢!

最佳答案

最新版本的 Flask-SocketIO 配置了关于跨源设置的最安全设置,即只允许同源。如果您的前端应用程序和 Flask 应用程序在不同的服务器或端口上运行,那么您必须配置跨域以便它们可以协同工作。

例如,如果您的前端托管在 http://localhost:3000,您可以允许它作为来源:

socketio = SocketIO(app, cors_allowed_origins='http://localhost:3000')

关于python - flask-socketio 服务器和 python-socketio 之间的安全通信,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58291543/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com