2024-05-10|閱讀時間 ‧ 約 24 分鐘

【💊 Python的解憂錦囊】當websockets遇到自簽證書的伺服端時

    raw-image


    前段時間我們有介紹「【Python 軍火庫🧨 - websockets】雙向溝通的渠道」, 這種方式可以達到基本的連線沒問題,但隨著資安意識的抬頭, 我們的websocket連線也會需要在通道之上進行加密, 那麼我們將根據使用情境來教您如何選用適當的連線。

    Server端

    我們的Server端套用了FastAPI框架, 以這樣的寫法載入SSL憑證:

        uvicorn.run(
    app,
    host='0.0.0.0',
    port=int(args.port),
    ssl_keyfile=args.ssl_keyfile,
    ssl_certfile=args.ssl_certfile,
    )

    Client端

    您可能會透過「【Prompt Engineering 提示工程】Ep.1 什麼是Prompt Engineering?」的技巧去詢問AI問題, 但直觀的會得到這樣的答案:

    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    ssl_context.load_verify_locations('/path/to/your/certificate.pem')
    async with websockets.connect(
    'wss://your.websocket.server',
    ssl=ssl_context,
    ) as websocket:
    ...

    這很正確沒錯, 確實在生產環境使用這種標準方式非常安全, 但麻煩的是還需要這個憑證檔(.pem), 有時候我們在其他臺主機想要快速連線, 又不希望帶上憑證檔時該怎麼辦呢?

    這時候聰明的我們可能會這樣問ChatGPT, 請問「如果我不想用pem連線, 而是希望用insecure」, 那麼它可能回答我們這樣的問題:

    async with websockets.connect(
    'ws://your.websocket.server', # 使用 ws://,而不是 wss://
    ssl=False, # 关闭 SSL/TLS 连接的证书验证
    ) as websocket:
    ...

    這看起來很合理對吧! 但別忘了開頭有提到我們的伺服器是以SSL方式架設, 這跑下去肯定會 💣 , 果不其然發生了這樣的錯誤…

    connect() received a ssl argument for a ws:// URI, use a wss:// URI to enable TLS

    不死心的我們加了點變化, 強制在URL用wss連線, 結果…

     did not receive a valid HTTP response

    !!! 難道沒招了嗎? 不不不, 既然我們的https都有insecure的連線方式了, 難道websocket沒有嗎? 這不可能, 沒關係, 我知道您現在也非常納悶為什麼 ssl=False沒有用, 就讓我們來分享一下正確的使用方式吧!

    🌟 本章精華重點

    ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    ssl_context.check_hostname = False
    ssl_context.verify_mode = ssl.CERT_NONE

    async with websockets.connect(
    'wss://your.websocket.server',
    ssl=ssl_context,
    ) as websocket:
    ...

    結語

    我們學會與AI合作固然是好事, 但它給的答案並不能完全信任, 在這之前我們還是得具有獨立思考的能力, AI僅是輔助我們快速思考的工具, 最終驗證與決策還是要回歸自身, 因此得到答案後也應一步步驗證再進行分享, 避免垃圾近、垃圾出的狀況導致誤解, 造成錯誤的結果。

    分享至
    成為作者繼續創作的動力吧!
    © 2024 vocus All rights reserved.