檢視原始碼 使用 SSL
若要準備一個應用程式透過 SSL 服務要求,我們需要加入一些設定,以及兩個環境變數。對 SSL 而言,實際上我們需要從憑證授權機構取得金鑰檔和憑證檔。我們需要的環境變數,就是這兩個檔案的路徑。
設定包含一個新的 https:
鍵,這是一個端點的關鍵字清單,其值則是埠號、金鑰檔路徑,以及憑證 (PEM) 檔路徑。如果我們加入 otp_app:
鍵,其值是我們應用程式的名稱,Plug 便會從我們的應用程式根目錄開始搜尋。接著我們可以將這些檔案放入 priv
目錄,並設定路徑為 priv/our_keyfile.key
和 priv/our_cert.crt
。
以下是 config/runtime.exs
中的範例設定。
import Config
config :hello, HelloWeb.Endpoint,
http: [port: {:system, "PORT"}],
url: [host: "example.com"],
cache_static_manifest: "priv/static/cache_manifest.json",
https: [
port: 443,
cipher_suite: :strong,
otp_app: :hello,
keyfile: System.get_env("SOME_APP_SSL_KEY_PATH"),
certfile: System.get_env("SOME_APP_SSL_CERT_PATH"),
# OPTIONAL Key for intermediate certificates:
cacertfile: System.get_env("INTERMEDIATE_CERTFILE_PATH")
]
如果沒有 otp_app:
鍵,我們需要提供檔案的絕對路徑,不論它們在檔案系統中的任何位置,讓 Plug 能夠找到它們。
Path.expand("../../../some/path/to/ssl/key.pem", __DIR__)
在 https:
鍵下的選項會傳遞給 Plug 介面,通常是 Bandit
,接著它會使用 Plug.SSL
選取 TLS Socket 選項。請參閱 Plug.SSL.configure/1 文件,以取得更多關於可用選項及其預設值的資訊。Plug HTTPS 指南 和 Erlang/OTP ssl 文件也提供有價值的資訊。
開發中的 SSL
如果你希望在開發中使用 HTTPS,可以透過執行以下指令產生自簽憑證: mix phx.gen.cert
。這需要 Erlang/OTP 20 或更新的版本。
使用你的自簽憑證,你的開發設定在 config/dev.exs
中可以更新為執行 HTTPS 端點
config :my_app, MyAppWeb.Endpoint,
...
https: [
port: 4001,
cipher_suite: :strong,
keyfile: "priv/cert/selfsigned_key.pem",
certfile: "priv/cert/selfsigned.pem"
]
這可以取代你的 http
設定,或者你可以在不同的埠上執行 HTTP 和 HTTPS 伺服器。
強制 SSL
在許多情況下,你會希望強制所有進來的請求使用 SSL,方法是以重新導向 HTTP 到 HTTPS。這可透過設定端點組態中的選項 :force_ssl
完成。它預期會有一個選項清單,這些選項會轉送至 Plug.SSL
。預設情況下,它會在 HTTPS 請求中設定「strict-transport-security」標頭,強制瀏覽器永遠使用 HTTPS。如果傳送不安全的 (HTTP) 請求,它會使用 :url
組態中所指定的 :host
重新導向至 HTTPS 版本。例如
config :my_app, MyAppWeb.Endpoint,
force_ssl: [rewrite_on: [:x_forwarded_proto]]
若要動態地重新導向至目前請求的 主機
,請將 :force_ssl
組態中的 :host
設定為 nil
。
config :my_app, MyAppWeb.Endpoint,
force_ssl: [rewrite_on: [:x_forwarded_proto], host: nil]
在這些範例中, rewrite_on:
鍵指定了一個反向代理程式或負載平衡器於應用程式前所使用的 HTTP 標頭,用來表示請求是由 HTTP 或 HTTPS 接收的。有關將 TLS 卸載至外部元素的含意之詳細資訊,特別是與安全性 cookie 相關的部分,請參閱 Plug HTTPS 指南。請注意,該文件中傳遞給 Plug.SSL
的選項應使用 Phoenix 應用程式中的 force_ssl:
端點選項設定。
重要的是要注意, force_ssl:
是 編譯 期間的組態,因此通常會設定在 prod.exs
中,如果從 runtime.exs
設定時不會作用。
HSTS
HSTS 是「HTTP 嚴格傳輸安全」的縮寫,是一種允許網站宣告自身僅可透過安全連線 (HTTPS) 存取的機制。它的引入是為了防止會移除 SSL/TLS 加密的中間人攻擊。HSTS 會導致網路瀏覽器從 HTTP 重新導向至 HTTPS,以及拒絕連線,除非該連線使用 SSL/TLS。
在設定 force_ssl: [hsts: true]
時,將新增 Strict-Transport-Security
標頭,其中附有定義原則有效期間的最大生存期。現代網路瀏覽器會透過從 HTTP 重新導向至 HTTPS 等方式對此回應。定義 HSTS 的 RFC6797 也規定,瀏覽器應追蹤主機的原則並應用於其到期日為止。它進一步規定,根據原則,假設在 80 埠以外的任何埠上的傳輸已加密。
儘管在執行階段會建議 HSTS,但在 localhost 上存取應用程式時可能會導致意料之外的行為。例如,存取在 https://127.0.0.1:4000
啟用 HSTS 的應用程式,就會導致所有後續來自 localhost 的流量(第 80 埠例外)預期都會被加密。這會中斷傳送至電腦上與 Phoenix 應用程式無關,且可能不支援加密流量的其他本機伺服器或代理伺服器的流量。
如果您不小心為 localhost 啟用 HSTS,您可能需要重設瀏覽器的快取,瀏覽器才會再度接受來自 localhost 的 HTTP 流量。
針對 Chrome
- 開啟「開發人員工具」面板。
- 按住網址列旁邊的「重新載入」圖示,就會出現一個下拉式選單。
- 選取「清除快取並強行重新載入」。
針對 Safari
- 清除瀏覽器的快取。
- 移除
~/Library/Cookies/HSTS.plist
中的項目,或直接刪除整個檔案。 - 重新啟動 Safari。
針對其他瀏覽器,請查閱 HSTS 文件。
或者,將 force_ssl
上的 :expires
選項設定為 0
應該會使項目過期並停用 HSTS。
如需瞭解 HSTS 選項的更多資訊,請見 Plug.SSL。