Kotlin爬虫https安全校验问题

在使用Kotlin进行页面分析和爬取数据时,我们需要用到爬虫。但是如果是https协议,可能需要进行安全校验。

我们以某网站(内容保护,不指明)为例,使用Jsoup库进行爬取。

当我们运行时,会报错:

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1946)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:316)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:310)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1639)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:223)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1037)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:965)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1064)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1367)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1395)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1379)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1570)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1498)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:268)
	at java.net.URL.openStream(URL.java:1068)
	at kotlin.io.TextStreamsKt.readBytes(ReadWrite.kt:150)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:450)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:259)
	at sun.security.validator.Validator.validate(Validator.java:262)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:237)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1621)
	... 16 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:445)
	... 22 more

这就说明我们遇到了https的安全校验问题,下面是解决办法。

我们只需要创建一个方法:

package com.. // 你的包名

import java.security.SecureRandom
import java.security.cert.CertificateException
import java.security.cert.X509Certificate
import javax.net.ssl.HttpsURLConnection
import javax.net.ssl.SSLContext
import javax.net.ssl.X509TrustManager

fun trustAny() {
    try {
        HttpsURLConnection.setDefaultHostnameVerifier { _, _ -> true }
        val context = SSLContext.getInstance("TLS")
        context.init(null, arrayOf<X509TrustManager>(object : X509TrustManager {
            @Throws(CertificateException::class)
            override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            @Throws(CertificateException::class)
            override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
            }

            override fun getAcceptedIssuers(): Array<X509Certificate?> {
                return arrayOfNulls(0)
            }
        }), SecureRandom())
        HttpsURLConnection.setDefaultSSLSocketFactory(context.socketFactory)
    } catch (e: Exception) {
        // e.printStackTrace()
    }
}

在抓取前使用 trustAny() 方法即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Kotlin 中,可以使用位运算符 `xor` 来实现异或校验。具体实现可以参考以下代码: ```kotlin fun xorCheck(bytes: ByteArray): Byte { var result = 0.toByte() for (byte in bytes) { result = result xor byte } return result } ``` 这个函数接收一个字节数组 `bytes`,并返回一个字节,这个字节是 `bytes` 中所有元素的异或结果。在函数中,我们定义了一个变量 `result`,并将其初始化为 0。然后,我们遍历 `bytes` 中的每个元素,并将其与 `result` 进行异或运算,将结果赋值给 `result`。最终,函数返回 `result`,即为异或校验的结果。 如果需要进行校验的字节数组中包含校验位,则可以将校验位从字节数组中剔除,然后再调用 `xorCheck` 函数进行校验。例如,如果字节数组中的最后一个元素为校验位,则可以使用以下代码进行校验: ```kotlin val data = byteArrayOf(0x01, 0x02, 0x03, 0x04, 0x05) val check = data.last() // 获取校验位 val result = xorCheck(data.dropLast(1).toByteArray()) // 剔除校验位后进行校验 if (check == result) { // 校验通过 } else { // 校验失败 } ``` 在这个例子中,我们首先使用 `last()` 函数获取字节数组中的最后一个元素,即为校验位。然后,我们使用 `dropLast()` 函数将校验位从字节数组中剔除,生成一个新的字节数组,然后再调用 `xorCheck` 函数进行校验。最后,我们将 `xorCheck` 函数的返回值与校验位进行比较,如果相等,则校验通过,否则校验失败。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值