Ktor 服务器中的 SSL 和证书
所需依赖项: io.ktor:ktor-network-tls-certificates
在大多数情况下,你的 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
构件:
以下代码片段展示了如何生成证书并将其保存到密钥库文件:
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 } } }
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。