java 与kotlin_与Kotlin和Ktor的ssl

java 与kotlin

So, you develop some of your services with Kotlin and Ktor.

因此,您可以通过Kotlin和Ktor开发一些服务。

Normally, your Ktor services will sit safely behind a reverse proxy, that will handle all the basic security concerns, including SSL, for you.

通常,您的Ktor服务将安全地放在反向代理后面,该代理将为您处理所有基本的安全问题,包括SSL。

And in your test environment, you would be running without SSL at all, simply bypassing all security. That’s usually the case.

并且在您的测试环境中,您将根本不需要SSL,而绕过所有安全措施。 通常就是这种情况。

But in my case, I had a particular HTTP client that I needed to test, that would only support HTTPS.

但就我而言,我有一个需要测试的特定HTTP客户端,该客户端仅支持HTTPS。

Unfortunately, the official documentation for Ktor is very confusing about self-signed certificates. For one, it only covers the case where you’re using applcation.conf to set up your server.

不幸的是, Ktor官方文档对自签名证书非常困惑。 首先,它仅涉及使用applcation.conf设置服务器的情况。

So, I decided to document here my findings on how to setup your own HTTPS test server with Ktor.

因此,我决定在这里记录我的发现,以了解如何使用Ktor设置自己的HTTPS测试服务器。

First, you’ll need additional dependency to support SSL.

首先,您需要其他依赖项来支持SSL。

In your build.gradle.kts add the following dependency:

在您的build.gradle.kts添加以下依赖项:

val ktorVersion = "1.4.0"
dependencies {
...
testImplementation("io.ktor:ktor-network-tls-certificates:$ktorVersion")
}

Notice that I’m using testImplementation here, specifically so you won’t use this solution in your production code.

注意,我在这里使用了testImplementation ,因此您不会在生产代码中使用此解决方案。

Now we can start the real work.

现在我们可以开始实际工作了。

So, we want to start our Ktor server in HTTPS mode. For that we’ll need to define a keystore. You can do that from a command line, but I wanted to be able to do that programatically.

因此,我们想以HTTPS模式启动Ktor服务器。 为此,我们需要定义一个密钥库。 您可以从命令行执行此操作,但我希望能够以编程方式执行该操作。

First, we’ll need two important variables that must be aligned: an alias for our certificate and a password for the keystore:

首先,我们需要两个必须对齐的重要变量:证书的别名和密钥库的密码

val alias = "certificateAlias"
val pass = "bcd"

Next, we’ll define our keystore. Keystore may contain multiple certificates that use different algorithms, but here I’ll be using only a single certificate:

接下来,我们将定义密钥库。 密钥库可能包含使用不同算法的多个证书,但是在这里,我将仅使用一个证书:

val keystore = buildKeyStore {certificate(alias) {hash = HashAlgorithm.SHA256
sign = SignatureAlgorithm.ECDSA
keySizeInBits = 256
password = pass
} // More certificates come here}

Next comes the definition of our server. This is were things start to get a bit more complicated:

接下来是我们服务器的定义。 这是事情开始变得更加复杂的地方:

val server = embeddedServer(Netty, applicationEngineEnvironment {
...
})

Notice that this is different from how we usually define our Ktor server:

请注意,这与我们通常定义Ktor服务器的方式不同:

val server = embeddedServer(Netty, 8080) {
...
}

Those two pieces of code may look similar, but the top block represents ApplicationEngineEnvironment, while the bottom block represents a Module. Those are distinctly different. And to set up SSL, we need to use ApplicationEngineEnvironment

这两段代码看起来很相似,但是最上面的方框代表ApplicationEngineEnvironment ,而最下面的方框代表Module 。 这些明显不同。 并设置SSL,我们需要使用ApplicationEngineEnvironment

Having ApplicationEngineEnvironment , we now can define sslConnector

有了ApplicationEngineEnvironment ,我们现在可以定义sslConnector

applicationEngineEnvironment {sslConnector(keystore,
alias,
{ "".toCharArray() },
{ pass.toCharArray() }) {
...
}
}

We’re using alias, password and keystore we’ve defined above.

我们正在使用我们在上面定义的别名密码密钥库

Now, since we didn’t have a chance to define on which port our server starts, we may as well do so now:

现在,由于我们没有机会定义服务器从哪个端口启动,因此我们现在也可以这样做:

sslConnector(...) {port = 8443
keyStorePath = keyStore.asFile.absoluteFile
...
}

And, as you see, we also must define key store path as well here.

而且,如您所见,我们还必须在此处定义密钥存储路径。

asFile is an extension property we’ve defined for simplicity:

asFile是为简单起见而定义的扩展属性:

private val KeyStore.asFile: File
get() {
val keyStoreFile = File("build/temp.jks")
this.saveToFile(keyStoreFile, pass)
return keyStoreFile
}

Now, if you invoke server.start() , you should see in you console:

现在,如果调用server.start() ,则应该在控制台中看到:

Responding at https://0.0.0.0:8443

But wait, didn’t we forget something? It’s pretty pointless to have a server that doesn’t have any routes defined.

但是等等,我们不是忘记了什么吗? 没有定义任何路由的服务器是毫无意义的。

You may be tempted to do it as usual:

您可能会像往常一样尝试这样做:

applicationEngineEnvironment {sslConnector(...) {
...
}
routing {
...
}
}

But this won’t work. Remember that usually, we operate in a context of a Module, but here we’re in a context of ApplicationEngineEnvironment

但这行不通。 请记住,通常,我们在Module的上下文中操作,但是在这里我们在ApplicationEngineEnvironment的上下文中

So, we’ll need to declare a module first:

因此,我们需要先声明一个模块:

applicationEngineEnvironment {sslConnector(...) {
...
}
module {
...
}
}

And now we can declare our routes as usual:

现在我们可以像往常一样声明路线了:

applicationEngineEnvironment {sslConnector(...) {
...
}
module {
routes {
...
}
}
}

And that’s it. You can see the full example here:

就是这样。 您可以在此处看到完整的示例:

import io.ktor.network.tls.certificates.buildKeyStore
import io.ktor.network.tls.certificates.saveToFile
import io.ktor.network.tls.extensions.HashAlgorithm
import io.ktor.network.tls.extensions.SignatureAlgorithm
import io.ktor.routing.routing
import io.ktor.server.engine.applicationEngineEnvironment
import io.ktor.server.engine.embeddedServer
import io.ktor.server.engine.sslConnector
import io.ktor.server.netty.Netty
import io.ktor.server.netty.NettyApplicationEngine
import java.io.File
import java.security.KeyStore


class HttpsServer {
    val pass = "abcd1234"


    val server: NettyApplicationEngine


    init {
        server = createServer()
    }


    private fun createServer(): NettyApplicationEngine {
        val alias = "certificateAlias"


        val keystore = buildKeyStore {
            certificate(alias) {
                hash = HashAlgorithm.SHA256
                sign = SignatureAlgorithm.ECDSA
                keySizeInBits = 256
                password = pass
            }
        }


        val server = embeddedServer(Netty, applicationEngineEnvironment {
            sslConnector(keystore,
                    alias,
                    { "".toCharArray() },
                    { pass.toCharArray() }) {
                port = 8181
                keyStorePath = keyStore.asFile.absoluteFile


                module {
                    // Your usual definitions, such as Content Negotiation, go here
                    routing {
                        // Your routes go here
                    }
                }
            }
        })


        return server
    }


    fun start() {
        server.start()
    }


    private val KeyStore.asFile: File
        get() {
            val keyStoreFile = File("build/temp.jks")
            this.saveToFile(keyStoreFile, pass)
            return keyStoreFile
        }
}

Remember, you should use this only for testing purposes, and never in production.

请记住,仅应将其用于测试目的,而不应在生产中使用。

翻译自: https://proandroiddev.com/ssl-with-kotlin-and-ktor-61b3d7dccbc5

java 与kotlin

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值