10.11. HTTPS——伺服器的傳輸加密

到目前為止,一切都是在連接埠 80 上的純 HTTP。任何能在瀏覽器與相機之間擷取封包的人,都能讀到登入表單的密碼、由它回傳的 session cookie、Authorization 標頭中的 JWT,以及每一張擷取影格的 JPEG 位元組。HTTPS 會對整條線路進行端對端加密。

憑證的工作流程本身——為開發產生自簽憑證、為正式環境取得 CA 簽署的憑證、以正確格式把檔案複製到相機上——涵蓋於 使用 TLS 憑證。本頁談的是 把一個已載入的憑證接進 microdot

10.11.1. 建立 SSL 環境

ssl.SSLContext 是標準函式庫中用來容納憑證、金鑰與協定選項的容器。對於伺服器,你會想要 PROTOCOL_TLS_SERVER,並從相機的檔案系統載入憑證鏈:

import ssl

ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
ctx.load_cert_chain('/flash/cert.der', '/flash/key.der')

DER 路徑取決於你在 TLS 章節中執行的工作流程——開發用自簽,正式環境用 CA 簽署。這些檔案不一定要放在 /flash 上;/sdcard 也同樣可行。

10.11.2. 把環境傳給 start_server

與先前的 start_server() 呼叫唯一的差別,就是 ssl=ctx 引數與連接埠號碼。連接埠 443 是 HTTPS 的預設值,這代表瀏覽器不需要輸入 :443——只要 https://yard-cam.local/ 就能用:

async def main():
    await asyncio.gather(
        capture_loop(),
        motion_detector(),
        app.start_server(host='0.0.0.0', port=443, ssl=ctx),
    )

asyncio.run(main())

伺服器端就這樣了。每一個現有的路由——/status/snapshot.jpg/stream.jpg/config/events/control、靜態儀表板——現在都透過 TLS 執行,且不需要任何其他程式碼變更。

10.11.4. 本頁未涵蓋的內容

HTTP 嚴格傳輸安全 (HSTS)、憑證自動續期、相機端用於對外請求的 CA 信任鏈,以及加密套件的選擇,這些全都放在 TLS 章節。本頁的接入——一個 SSLContext、一個 ssl=ctx——是唯一專屬於 microdot 的部分。

儀表板網址列現在從 http:// 變成 https://,而 WebSocket 從 ws:// 變成 wss://——儀表板的 JavaScript 早已根據 location.protocol 選用了正確的協定方案,所以不需要任何用戶端變更。

相機透過 HTTPS 提供服務。登入表單、JWT 與擷取的影格在傳輸過程中都被加密了。