我需要抓取已过期/自签名证书的公司内部网站。没有人会为该主机配置有效的证书,因此我必须使用不安全的连接。curl
为此具有--insecure
标志,
Scala finagle库具有.tlsWithoutValidation()
模式。
问题:是否有一个Kotlin库具有类似的选项?
UPD :到目前为止,我正在使用Fuel并找到了here,但仍在寻找更好的方法。
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)
}
上述解决方法行得通,但是它太冗长,似乎为我的应用程序建立的每个连接设置了不安全的模式,而不仅是针对特定的设置。
最佳答案
Fuel允许您通过FuelManager
类创建自己的Fuel客户端实例。管理器允许您设置自己的HostnameVerifier
和SSLSocketFactory
,然后使用配置的客户端创建一个客户端。参见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 }
}
然后,要检查仅通过此自定义
FuelManager
进行的连接是不受信任的,而不信任的连接是不受信任的,请执行以下操作: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: ...
定制
FuelManager
之所以能够成功发出请求,是因为它信任所有证书,但是对于未使用定制管理器的连接,我们可以看到它返回javax.net.ssl.SSLHandshakeException
。关于ssl - 可以进行httpS连接而无需证书验证的kotlin库(例如curl --insecure),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47460211/