kotlin library that can do httpS connection without certificate verification (like curl --insecure)

匿名 (未验证) 提交于 2019-12-03 01:38:01

问题:

I need to crawl internal company site that has expired/self-signed certificate. Noone is ever going to configure valid certificate for that host, so I have to use insecure connection.

curl has --insecure flag for that purpose,

Scala finagle library has .tlsWithoutValidation() mode.

QUESTION: Is there a Kotlin library that has similar option?

UPD: so far I am using Fuel with the javish workaround found here but still searching for better ways..

fun useInsecureSSL() {      // Create a trust manager that does not validate certificate chains     val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {         override fun getAcceptedIssuers(): Array<X509Certificate>? = null         override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) = Unit         override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) = Unit     })      val sc = SSLContext.getInstance("SSL")     sc.init(null, trustAllCerts, java.security.SecureRandom())     HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory)      // Create all-trusting host name verifier     val allHostsValid = HostnameVerifier { _, _ -> true }      // Install the all-trusting host verifier     HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid) }

The above workaround works however it is too verbose and seems to set insecure mode for every connection made by my app, not only for the particular one.

回答1:

Fuel allows you to create your own instance of the Fuel client through the FuelManager class. The manager lets you can set your own HostnameVerifier and SSLSocketFactory and then creates a client with those configured. See https://github.com/kittinunf/Fuel/blob/1.16.0/fuel/src/main/kotlin/com/github/kittinunf/fuel/core/FuelManager.kt#L31-L43

val manager : FuelManager = FuelManager().apply {   val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {     override fun getAcceptedIssuers(): Array<X509Certificate>? = null     override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) = Unit     override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) = Unit   })    socketFactory = SSLContext.getInstance("SSL").apply {     init(null, trustAllCerts, java.security.SecureRandom())   }.socketFactory    hostnameVerifier = HostnameVerifier { _, _ -> true } }

Then to check that only connections that goes through this custom FuelManager is untrusted and connections that don't are trusted, we do this:

val (_, untrustedResp, untrustedResult) = manager.request(Method.GET, "https://internal/company/site").response() assert(untrustedResp.statusCode == 200) val (bytes, _) = untrustedResult assert(bytes != null)   val (_, trustedResp, trustedResult) = "https://internal/company/site".httpGet().response() assert(trustedResp.statusCode != 200) val (bytes, error) = trustedResult assert(bytes == null) println(error) // javax.net.ssl.SSLHandshakeException: PKIX path building failed: ...

The custom FuelManager was able to make the request successfully because it trusts all certs but for the connection that didn't use the custom manager, we can see that it returns with javax.net.ssl.SSLHandshakeException.



回答2:

Thanks, @ludenus, @Jason Yeo.

If you use Fuel and want to overcome old SSL certificate problem, then in your Api-class where you keep all requests, write what they suggested. This solution doesn't check any URL, it allows requests to any URLs.

import com.github.kittinunf.fuel.core.FuelManager import com.github.kittinunf.fuel.core.Method import com.github.kittinunf.fuel.core.Request import com.github.kittinunf.fuel.httpPost import java.security.cert.X509Certificate import javax.net.ssl.HostnameVerifier import javax.net.ssl.SSLContext import javax.net.ssl.TrustManager import javax.net.ssl.X509TrustManager  class ApiImpl : Api {      init {         FuelManager.instance.basePath = Api.SERVER_URL // Your usual URL.          FuelManager.instance.apply {             val trustAllCerts = arrayOf<TrustManager>(object : X509TrustManager {                 override fun getAcceptedIssuers(): Array<X509Certificate>? = null                 override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) =                     Unit                 override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) =                     Unit             })              socketFactory = SSLContext.getInstance("SSL").apply {                 init(null, trustAllCerts, java.security.SecureRandom())             }.socketFactory              hostnameVerifier = HostnameVerifier { _, _ -> true }         }     }      /**      * Your requests stay intact.      */     override fun getSomething(id: Int): Request =         "getinfo/".httpPost(listOf("id" to id)) }


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!