具有自签名证书的ktor客户端https请求

时间:2018-12-12 08:53:57

标签: kotlin ktor

我有一个运行有自签名证书的Ktor服务器应用程序(REST API)。

从浏览器(在警告和确认之后),它可以正常工作,端口80重定向到8443。

但是,如果我从Ktor Apache客户端尝试此操作:

fun main(args: Array<String>) = runBlocking {

    val client = HttpClient(Apache) {
        install(JsonFeature) {
            serializer = GsonSerializer()
        }
    }

    val job = GlobalScope.launch {
        try {
            //self-signed certificate
            val resultWillFail = client.get<String>("https://10.0.0.11:8443/get-my-services")
            println("${resultWillFail}")
            val resultOk = client.get<String>("https://en.wikipedia.org/wiki/Main_Page") //ok
            println("${resultOk}")
        } catch (e: Exception) {
            println("Error: ${e.message}")
        }
    }

    job.join()
}

我对https://10.0.0.11:8443/get-my-services的请求将失败:

  

错误:常规SSLEngine问题

我也使用curl尝试过相同的操作

  

卷曲:(77)schannel:下一个InitializeSecurityContext失败:SEC_E_UNTRUSTED_ROOT(0x80090325)-颁发了证书链   由不受信任的权威机构。

所以我的问题是:如何在ktor客户端(Apache)中使用自签名证书?

谢谢, J

2 个答案:

答案 0 :(得分:2)

您需要配置Apache HttpClient忽略自签名证书,并将其传递给KTor。根据信息here,您可以使用以下代码忽略自签名证书验证:

// use the TrustSelfSignedStrategy to allow Self Signed Certificates
val sslContext = SSLContextBuilder
        .create()
        .loadTrustMaterial(TrustSelfSignedStrategy())
        .build()

val allowAllHosts = NoopHostnameVerifier()
val connectionFactory = SSLConnectionSocketFactory(sslContext, allowAllHosts)

val client = HttpClients
        .custom()
        .setSSLSocketFactory(connectionFactory)
        .build() 

最后要做的就是在KTor代码中使用客户端。我还没有尝试过,但是让我知道你的情况。

答案 1 :(得分:2)

基于Erik的答案,这就是我如何使Ktor Apache Client接受自签名证书:

fun main(args: Array<String>) = runBlocking {
    val client = HttpClient(Apache) {
        install(JsonFeature) {
            serializer = GsonSerializer()
        }
        engine {
            customizeClient {
                setSSLContext(
                    SSLContextBuilder
                        .create()
                        .loadTrustMaterial(TrustSelfSignedStrategy())
                        .build()
                )
                setSSLHostnameVerifier(NoopHostnameVerifier())
            }
        }
    }

    val job = GlobalScope.launch {
        try {
            val sslGetResult = client.get<String>("https://10.0.0.11:8443/get-my-services")
            println("${sslGetResult}")
        } catch (e: Exception) {
            println("Error: ${e.message}")
        }
    }

    job.join()
}