【问题标题】:How to create Python secure websocket client request?如何创建 Python 安全 websocket 客户端请求?
【发布时间】:2017-10-20 15:08:13
【问题描述】:

我的 Python 安全 websocket 客户端代码给了我如下异常:

[SSL: CERTIFICATE_VERIFY_FAILED] 证书验证失败 (_ssl.c:748)

我也创建了我的私有证书和签名证书,但我无法使用 Python 脚本连接到它,如下所示:

import json
from websocket import create_connection


class subscriber:
   def listenForever(self):
   try:
      # ws = create_connection("wss://localhost:9080/websocket")
      ws = create_connection("wss://nbtstaging.westeurope.cloudapp.azure.com:9090/websocket")
      ws.send("test message")
      while True:
          result = ws.recv()
          result = json.loads(result)
          print("Received '%s'" % result)

      ws.close()
  except Exception as ex:
      print("exception: ", format(ex))


try:
    subscriber().listenForever()
except:
    print("Exception occured: ")

我在 python 中的 https/wss 服务器脚本与 tornado 如下:

import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import os
import ssl

ssl_root = os.path.join(os.path.dirname(__file__), 'ssl1_1020')


class WebSocketHandler(tornado.websocket.WebSocketHandler):
    def check_origin(self, origin):
        return True

    def open(self):
        pass

    def on_message(self, message):
        self.write_message("Your message was: " + message)
        print("message received: ", format(message))

    def on_close(self):
        pass


class IndexPageHandler(tornado.web.RequestHandler):
    def get(self):
        self.render("index.html")


class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
           (r'/', IndexPageHandler),
           (r'/websocket', WebSocketHandler),
        ]

        settings = {
            'template_path': 'templates'
        }
        tornado.web.Application.__init__(self, handlers, **settings)


ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_ctx.load_cert_chain(ssl_root+"/server.crt",
                    ssl_root + "/server.pem")


if __name__ == '__main__':
    ws_app = Application()
    server = tornado.httpserver.HTTPServer(ws_app, ssl_options=ssl_ctx,)
    server.listen(9081, "0.0.0.0")
    print("server started...")
    tornado.ioloop.IOLoop.instance().start()

用于创建 SSL 签名证书的步骤:

openssl genrsa -des3 -out server.key 1024
openssl rsa -in server.key -out server.pem
openssl req -new -nodes -key server.pem -out server.csr
openssl x509 -req -days 365 -in server.csr -signkey server.pem -out server.crt

【问题讨论】:

标签: python-3.x websocket openssl tornado azure-web-app-service


【解决方案1】:

最后我找到了一个解决方案,我更新了 python 客户端脚本,同时连接到安全的 web socket url 以忽略证书请求,如下所示:

 import ssl
 import websocket

 ws = websocket.WebSocket(sslopt={"cert_reqs": ssl.CERT_NONE})
 ws.connect("wss://xxx.com:9090/websocket")

【讨论】:

    【解决方案2】:

    对我来说,忽略错误不是一种选择,我不得不使用我的自签名证书,因为 SSL pinning 在复杂的 IoT 环境中:

    import asyncio
    import pathlib
    import ssl
    import websockets
    
    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    localhost_pem = pathlib.Path(__file__).with_name("localhost.pem")
    ssl_context.load_verify_locations(localhost_pem)
    
    async def hello():
        uri = "wss://localhost:8765"
        async with websockets.connect(
            uri, ssl=ssl_context
        ) as websocket:
            name = input("What's your name? ")
    
            await websocket.send(name)
            print(f"> {name}")
    
            greeting = await websocket.recv()
            print(f"< {greeting}")
    
    asyncio.get_event_loop().run_until_complete(hello())
    

    在 websocket 存储库的示例文件夹中找到 here

    附言

    我将它从 SSLContext(ssl.PROTOCOL_TLS_CLIENT) 更改为 SSLContext(ssl.PROTOCOL_TLSv1_2) 以使其正常工作

    【讨论】:

    • 最后,在尝试修复错误 3 天后,这对我有用。非常感谢!
    【解决方案3】:

    如果将来有人好奇为什么 wss python 服务器失败是因为这里的 tornado 文档:

    当使用带有自签名证书的安全 websocket 连接 (wss://) 时,来自浏览器的连接可能会失败,因为它想要显示“接受此证书”对话框但无处显示。您必须首先使用相同的证书访问常规 HTML 页面以接受它,然后 websocket 连接才会成功。

    【讨论】:

    • 例如,如果websocket在localhost:4000,你就必须访问https://localhost:4000并接受风险。
    【解决方案4】:

    仅出于测试目的尝试以下操作。下面是一个非常不安全的kluge:

    import asyncio, ssl, websockets
    
    #todo kluge
    #HIGHLY INSECURE
    ssl_context = ssl.SSLContext()
    ssl_context.check_hostname = False
    ssl_context.verify_mode = ssl.CERT_NONE
    #HIGHLY INSECURE
    #todo kluge
    
    uri = "wss://myAwesomeSSL.wss.kluge"
    
    async with websockets.connect(uri, ssl=ssl_context) as websocket:
            greeting = await websocket.recv()
            print(f"< {greeting}")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      • 1970-01-01
      • 2017-05-29
      • 2017-02-10
      相关资源
      最近更新 更多