【问题解决】Gradle wrapper 下载出现 ssl 异常 javax.net.ssl.SSLHandshakeException 的问题解决

1. 问题出现

通过 ./gradlew 命令来执行任务的时候,会先对gradle 进行下载,但是在下载的过程出现了SSL握手异常,异常日志如下:

$ ./gradlew -Pci --console=plain lintDebug -PbuildDir=lint
Downloading https://services.gradle.org/distributions/gradle-4.6-all.zip

Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
	at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2020)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1127)
	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.followRedirect0(HttpURLConnection.java:2729)
	at sun.net.www.protocol.http.HttpURLConnection.followRedirect(HttpURLConnection.java:2641)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1824)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1492)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:263)
	at org.gradle.wrapper.Download.downloadInternal(Download.java:66)
	at org.gradle.wrapper.Download.download(Download.java:51)
	at org.gradle.wrapper.Install$1.call(Install.java:62)
	at org.gradle.wrapper.Install$1.call(Install.java:48)
	at org.gradle.wrapper.ExclusiveFileAccessManager.access(ExclusiveFileAccessManager.java:69)
	at org.gradle.wrapper.Install.createDist(Install.java:48)
	at org.gradle.wrapper.WrapperExecutor.execute(WrapperExecutor.java:107)
	at org.gradle.wrapper.GradleWrapperMain.main(GradleWrapperMain.java:61)
ERROR: Job failed: exit status 1

2. 分析过程

从日志来看,是因为在下载 gradle-4.6-all.zip 文件的时候出现了 .SSLHandshakeException: Received fatal alert: handshake_failure 的异常,下载链接是:https://services.gradle.org/distributions/gradle-4.6-all.zip 。

然后试着通过浏览器打开这个链接,发现它会自动重定向到:https://downloads.gradle-dn.com/distributions/gradle-4.6-all.zip 同时也打不开,并在Chrome浏览器中显示了以下错误信息:

此网站无法提供安全连接 downloads.gradle-dn.com 使用了不受支持的协议。
ERR_SSL_VERSION_OR_CIPHER_MISMATCH
协议不受支持
客户端和服务器不支持一般 SSL 协议版本或加密套件。

网上搜索了下,以上错误应该是本地认为服务端使用了“未受支持的的协议”导致的。

既然是 ssl 协议的握手失败,那么如果不使用 https 呢?于是把以上重定向后的url改成http 协议的如下:

http://downloads.gradle-dn.com/distributions/gradle-4.6-all.zip

这个url在浏览器中打开就正常了

3. 初步解决

既然发现了一个能够正常打开的下载地址,那么一个简单的解决方案就有了,那就是修改 gradle-wrapper.properties 文件中的下载地址,原有的内容如下:

distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

把其中的下载链接改成 http 协议的就行了:

distributionUrl=http\://services.gradle.org/distributions/gradle-4.6-all.zip

修改后,执行./graldew build,一切正常。

4. 根本解决

如果只是为了单纯地解决这个问题,那么到这里其实已经可以结束了,但是本着刨根问底(zuan niu jiao jian)的原则,我是不甘心就这么解决的。

回望这个问题,本质上是本地在下载远程的gradle wrapper 文件的时候本地的安全协议和远程的不一致导致的,那么问什么会这样呢?

搜集了一番之后,在gradle 的github issue列表里面,找到了一个相同的问题: https://github.com/gradle/gradle/issues/5736 ,但是看状态是已经解决了的。从问题的结论来看,原因是因为services.gradle.org 的根证书使用的是 COMODO ECC Certification Authority 提供的,但是在前端没有被信任。

所以,结论就是本质上网络环境的问题,本质解决就是。。。没有

5. 后记

在以上问题的解决过程中,曾经测试过挂上一个远程的代理(FQ)来测试,发现那个会出问题的url就正常了,可见这个ssl的验证和我们复杂的网络环境还是存在一定的关系的。

参考资料:

https://www.jianshu.com/p/d23ceed8f19d

你可能感兴趣的:(Android,Gradle,问题解决)