Ktor Server 中的 SSL 与证书
所需依赖项:io.ktor:ktor-network-tls-certificates
在大多数情况下,您的 Ktor 服务会部署在 Nginx 或 Apache 等反向代理之后。 这意味着反向代理服务器负责处理安全事务,包括 SSL。
如有必要,您可以通过提供证书路径将 Ktor 配置为直接提供 SSL 服务。 Ktor 使用 Java KeyStore (JKS) 作为证书的存储设施。 您可以使用 keytool 来转换和管理存储在密钥库中的证书。 如果您需要将证书颁发机构颁发的 PEM 证书转换为 Ktor 支持的 JKS 格式,这可能会非常有用。
您可以使用 Let's Encrypt 获取免费证书,以便在 Ktor 中处理
https://和wss://请求。
生成自签名证书
在代码中生成证书
Ktor 提供了通过调用 buildKeyStore 函数生成用于测试目的的自签名证书的能力,该函数会返回一个 KeyStore 实例。 要使用此函数,您需要在构建脚本中添加 ktor-network-tls-certificates 构件:
下面的代码片段展示了如何生成证书并将其保存到密钥库文件中:
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 格式颁发证书,您需要在在 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组中提供密钥库设置: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。
