Ktor 伺服器中的 SSL 與憑證
必要依賴:io.ktor:ktor-network-tls-certificates
程式碼範例: ssl-engine-main、 ssl-embedded-server
在大多數情況下,您的 Ktor 服務會放置在反向代理(例如 Nginx 或 Apache)後方。 這表示反向代理伺服器處理安全相關問題,包括 SSL。
如有必要,您可以透過提供憑證路徑來設定 Ktor 直接提供 SSL 服務。 Ktor 使用 Java KeyStore (JKS) 作為憑證的儲存設施。 您可以使用 keytool 來轉換和管理儲存在 KeyStore 中的憑證。 如果您需要將憑證授權單位頒發的 PEM 憑證轉換為 Ktor 支援的 JKS 格式,這可能會很有用。
您可以使用 Let's Encrypt 來獲取免費憑證,以便 Ktor 服務
https://
和wss://
請求。
產生自簽憑證
在程式碼中產生憑證
Ktor 提供了透過呼叫 buildKeyStore 函數來產生自簽憑證以用於測試目的的功能, 該函數會回傳一個 KeyStore 實例。 要使用此函數,您需要在建置腳本中添加 ktor-network-tls-certificates
artifact:
以下程式碼片段展示了如何產生憑證並將其儲存到密鑰儲存庫檔案:
private fun ApplicationEngine.Configuration.envConfig() {
val keyStoreFile = File("build/keystore.jks")
val keyStore = buildKeyStore {
certificate("sampleAlias") {
password = "foobar"
domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
}
}
keyStore.saveToFile(keyStoreFile, "123456")
}
由於 Ktor 在啟動時需要憑證,您必須在啟動伺服器之前建立憑證。 您可以在此處找到完整的範例:ssl-embedded-server。
使用 keytool 產生憑證
您可以使用 keytool 來產生自簽憑證:
keytool -keystore keystore.jks -alias sampleAlias -genkeypair -keyalg RSA -keysize 4096 -validity 3 -dname 'CN=localhost, OU=ktor, O=ktor, L=Unspecified, ST=Unspecified, C=US'
執行此命令後,keytool
會建議您指定密鑰儲存庫密碼,然後產生一個 JKS 檔案。
將 PEM 憑證轉換為 JKS
如果您的憑證授權單位頒發 PEM 格式的憑證,您需要將其轉換為 JKS 格式, 然後才能在 Ktor 中設定 SSL。 您可以使用 openssl
和 keytool
公用程式來完成此操作。 例如,如果您在 key.pem
檔案中有私鑰,在 cert.pem
中有公開憑證,轉換過程可能如下所示:
使用
openssl
透過以下命令將 PEM 轉換為 PKCS12 格式:Bashopenssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name "sampleAlias"
系統將提示您輸入
key.pem
的密碼,以及keystore.p12
的新密碼。使用
keytool
將 PKCS12 轉換為 JKS 格式:Bashkeytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -destkeystore keystore.jks
系統將提示您輸入
keystore.p12
檔案的密碼,以及keystore.jks
的新密碼。keystore.jks
將會被產生。
在 Ktor 中設定 SSL
在 Ktor 中指定 SSL 設定取決於用於設定 Ktor 伺服器的方式: 透過使用配置檔案或在程式碼中使用 embeddedServer
函數。
配置檔案
如果您的伺服器配置在 application.conf
或 application.yaml
配置檔案中,您可以使用以下屬性啟用 SSL:
使用
ktor.deployment.sslPort
屬性指定 SSL 埠號:shellktor { deployment { sslPort = 8443 } }
yamlktor: deployment: sslPort: 8443
在單獨的
security
群組中提供密鑰儲存庫設定:shellktor { security { ssl { keyStore = keystore.jks keyAlias = sampleAlias keyStorePassword = foobar privateKeyPassword = foobar } } }
yamlktor: security: ssl: keyStore: keystore.jks keyAlias: sampleAlias keyStorePassword: foobar privateKeyPassword: foobar
有關完整範例, 請參閱 ssl-engine-main。
embeddedServer
如果您使用 embeddedServer
函數來執行伺服器,您需要在 ApplicationEngine.Configuration 中配置自訂環境, 並使用 sslConnector 在其中提供 SSL 設定:
import io.ktor.network.tls.certificates.*
import io.ktor.server.application.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import org.slf4j.*
import java.io.*
import java.security.KeyStore
fun main() {
embeddedServer(Netty, applicationEnvironment { log = LoggerFactory.getLogger("ktor.application") }, {
envConfig()
}, module = Application::module).start(wait = true)
}
private fun ApplicationEngine.Configuration.envConfig() {
val keyStoreFile = File("build/keystore.jks")
val keyStore = buildKeyStore {
certificate("sampleAlias") {
password = "foobar"
domains = listOf("127.0.0.1", "0.0.0.0", "localhost")
}
}
keyStore.saveToFile(keyStoreFile, "123456")
connector {
port = 8080
}
sslConnector(
keyStore = keyStore,
keyAlias = "sampleAlias",
keyStorePassword = { "123456".toCharArray() },
privateKeyPassword = { "foobar".toCharArray() }) {
port = 8443
keyStorePath = keyStoreFile
}
}
有關完整範例, 請參閱 ssl-embedded-server。