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 構件:
下方的程式碼片段展示了如何產生憑證並將其儲存到 keystore 檔案中:
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 會建議您指定一個 keystore 密碼,接著便會產生一個 JKS 檔案。
將 PEM 憑證轉換為 JKS
如果您的憑證授權單位發行的是 PEM 格式的憑證,則在 於 Ktor 中配置 SSL 之前,您需要將其轉換為 JKS 格式。 您可以使用 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群組中提供 keystore 設定:shellktor { security { ssl { keyStore = keystore.jks keyAlias = sampleAlias keyStorePassword = foobar privateKeyPassword = foobar trustStore = truststore.jks trustStorePassword = foobar enabledProtocols = ["TLSv1.2", "TLSv1.3"] } } }yamlktor: security: ssl: keyStore: keystore.jks keyAlias: sampleAlias keyStorePassword: foobar privateKeyPassword: foobar trustStore: truststore.jks trustStorePassword: foobar enabledProtocols: ["TLSv1.2", "TLSv1.3"]
如需完整範例,請參閱 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。
