【问题标题】:kotlin connect to self-signed https serverkotlin 连接到自签名 https 服务器
【发布时间】:2018-02-28 14:56:36
【问题描述】:

我有以下 kotlin 代码:

val urlPath = "https://10.0.2.2:8080"
var data: String
try {
    data = URL(urlPath).readText()
} catch (e: Exception) {
    Log.e("doInBackground", "Exception caught: ${e.localizedMessage}")
    error = when (e) {
        is MalformedURLException -> "Invalid URL"
        is IOException -> "Network Error"
        else -> {
            "Network error: ${e.localizedMessage}"
        }
    }
}

如果我使用上面的代码连接到 http 服务器,上面的代码可以工作。但是,当我尝试使用自签名证书连接到 https 服务器时,它会失败。有没有办法允许本地主机上的 https 连接(仅),即使证书是自签名的?

【问题讨论】:

  • 服务器是否只允许相互认证?否则,您只需要使用自定义 TrustStore 信任提供的服务器证书
  • 这是一个简单的 golang https 服务器,通过 http.ListenAndServerTLS 启动,因此没有为相互身份验证配置任何额外内容。如何使用 URL 上的 kotlin 扩展创建 TrustStore?我无法从谷歌轻松找到任何代码示例。
  • 这不是 Kotlin 特定的,google for Java JSSE

标签: java android kotlin kotlin-android-extensions kotlin-extension


【解决方案1】:

这是一个使用 JSSE 从 https://google.com 读取的示例,它实际上信任每个证书,不应有效地使用。

fun main(args: Array<String>) {
    val urlPath = "https://google.com"
    try {
        (URL(urlPath).openConnection() as HttpsURLConnection).apply {
            sslSocketFactory = createSocketFactory(listOf("TLSv1.2"))
            hostnameVerifier = HostnameVerifier { _, _ -> true }
            readTimeout = 5_000
        }.inputStream.use {
            it.copyTo(System.out)
        }
    } catch (e: Exception) {
        TODO()
    }
}


private fun createSocketFactory(protocols: List<String>) =
    SSLContext.getInstance(protocols[0]).apply {
        val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {
            override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
            override fun checkClientTrusted(certs: Array<X509Certificate>, authType: String) = Unit
            override fun checkServerTrusted(certs: Array<X509Certificate>, authType: String) = Unit
        })
        init(null, trustAllCerts, SecureRandom())
    }.socketFactory

我有一个小图书馆来存放这些东西here,它既不是最新的也不是发布的。不过,它提供了一个简单的 DSL 来设置 TLS/SSL 套接字,并提供了 https 连接的方法。

【讨论】:

  • 这似乎不起作用。我仍然得到一个例外:03-01 00:09:27.667 5028-5088/com.example.logindemo E/doInBackground: Exception caught: Failed to connect to /10.0.2.2:8080
  • 嗯,这个例外对我没什么帮助
  • 啊等等。这是我的一个错误(在错误的端口上启动了服务器)。代码工作正常。我会接受答案。但是,我要求您考虑编辑代码以仅忽略“localhost”的证书检查(可能还有 10.0.2.2 也适用于 Android),而不是一揽子开放。谢谢。
  • 有人可以发给我一个来源,我可以从中理解发生了什么吗?虽然它解决了我的问题,但我不明白它是如何做到的,我真的很想详细了解发生了什么......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多