使用 Python SSL

Python SSL 程式庫的 2.7 版已淘汰。請改用最新版本,目前為 2.7.11

App Engine 透過 SSL 函式庫支援 Python 2.7 運行時的原生 Python SSL 函式庫,您必須將函式庫新增至應用程式中。

指定 SSL 函式庫

如果您想使用原生 Python SSL,請在應用程式的 app.yaml 中為 libraries 設定指定 ssl,以便啟用 SSL。您應使用最新的程式庫版本,目前為 2.7.11 版。此版本支援 TLS 的 1.0、1.1 以及 1.2 版本,並且對應於 Python 2.7.11 及後續版本的 SSL 版本。

libraries:
- name: ssl
  version: latest

提供授權憑證

若需執行 SSL 交握,您必須擁有包含串連憑證授權之憑證的檔案。您可以使用應用程式上傳自己的檔案,也可以使用 App Engine 提供的檔案:/etc/ca-certificates.crt

執行 SSL 交握

Python 2.7 wrap_socket 方法會採用兩個檔案名稱參數,其中包含用戶端的金鑰和憑證。在 App Engine 的環境中,此方法有所限制,因為應用程式無法寫入檔案,以動態提供不同的金鑰和憑證。為解決這項限制,ssl.wrap_socket 方法的 certfilekeyfile 參數可以是「類似檔案」的物件,讓應用程式以其他方式儲存憑證和金鑰,而非僅在已上傳的應用程式檔案中儲存。 (「類檔案」物件是具有「讀取」方法的物件,將整個憑證以字串型態傳回)。

  # Example of a dynamic key and cert.
  datastore_record_k = ndb.Key('Employee', 'asalieri', 'Address', 1)
  datastore_record = datastore_record_k.get()
  key_str = datastore_record.key_str
  cert_str = datastore_record.cert
  ssl_server = ssl.wrap_socket(server_sock,
                              server_side=False,
                              keyfile=StringIO.StringIO(key_str),
                              certfile=StringIO.StringIO(cert_str),
                              cert_reqs=ssl.CERT_REQUIRED,
                              ssl_version=ssl.PROTOCOL_SSLv23,
                              ca_certs=CERTIFICATE_FILE)

您不需要指定 ssl_version 參數。如果省略,2.7.11 程式庫會預設為 PROTOCOL_SSLv23。您也可以指定 PROTOCOL_TLSv1PROTOCOL_TLSv1_1PROTOCOL_TLSv1_2

wrap_socket 方法的 App Engine 實作項目包含必要參數 ca_certs,用於指定含有連結認證機構憑證的特殊檔案。

驗證憑證

您的應用程式需要驗證憑證,以預防安全漏洞,例如「攔截式」攻擊。

現在說明一下操作方式:

  1. 編輯 app.yaml 檔案,將環境變數 PYTHONHTTPSVERIFY 設為 1

     env_variables:
       PYTHONHTTPSVERIFY: 1
    
  2. 重新部署您的應用程式。

除了在 app.yaml 中指定憑證驗證外,您也可以在成功執行 SSL 握手後,明確呼叫 SSL 程式庫來執行驗證,如下所示:

    ssl.match_hostname(ssl_server.getpeercert(), 'a.hostname.com')

上述程式碼使用 match_hostname 功能,該功能已從 Python 3.2 回移至 App Engine Python 2.7.11 SSL 模組。此呼叫確保對等方提供的憑證會與對等方憑證中的一個指定主機相符。

在 dev_appserver 上執行

您可以使用 urlfetch API 發出 HTTPS 要求,使用 httplib 的 Dev_server 憑證驗證行為所用的 urlfetch,與生產 App Engine 環境的相同。Dev_appserver 不支援使用通訊端的請求。