Android 7.0上面.OpenSSLSocketImpl.startHandshake报异常问题

Android 7.0上面.OpenSSLSocketImpl.startHandshake报异常问题

最近在一个Android项目开发中用到https请求,https直白一点地说就是在http的基础上加了一层SSL或者TLS,主要是增加安全性。SSL或者TLS主要有三个作用:

1、  认证服务器,如果是双向认证的话,还需要认证客户端;

2、  对网络通信内容进行加密;

3、  防止通信内容在传输过程中被篡改。

 

访问https网站,客户端是需要一个证书的,这个证书是用来验证服务器传过来的密钥是否正确,如果发起https请求,网上有很多写法,想了解的同学可以去网上搜一下。我在项目中直接的用的是okhttp,okhttp封装了https的请求逻辑,它会读取设备上的信任证书去验证服务端的密钥,就是在用okhttp的过程中遇到了问题,问题日志如下:

07-1006:57:27.791  5558  7200 I System.out:javax.net.ssl.SSLHandshakeException:java.security.cert.CertPathValidatorException: Trust anchor for certificationpath not found.

07-1006:57:27.791  5558  7200 I System.out:        atcom.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)

07-1006:57:27.792  5558  7200 I System.out:        atcom.squareup.okhttp.internal.io.RealConnection.connectTls(RealConnection.java:188)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.io.RealConnection.connectSocket(RealConnection.java:145)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.io.RealConnection.connect(RealConnection.java:108)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:184)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.Call.getResponse(Call.java:286)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:243)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.Call$ApplicationInterceptorChain.proceed(Call.java:232)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.Call.getResponseWithInterceptorChain(Call.java:205)

07-10 06:57:27.792  5558 7200 I System.out:        atcom.squareup.okhttp.Call.execute(Call.java:80)

 

从日志上看,这是okhttp的RealConnection类调用了OpenSSLSocketImpl的startHandshake方法,在startHandshake方法的执行过程当中抛出了什么证书找不到的异常(Trust anchor for certification path not found),麻烦的是OpenSSLSocketImpl是android.jar中的一个类,碰到这个问题第一反应就是头大,话说okhttp和android.jar中的代码应该不会有问题啊,就是有问题,怎么改呢。起初是在网上搜那个异常的解决办法,搜到有很多,比如自己导入证书啊、屏蔽证书验证什么的,感觉都不靠谱,并且项目上用的请求都是okhttp,没时间在去自己写一套请求框架了。废话少说吧,后来搜索SSLSocket. startHandshake方法报错,才找到一些有用资料,原来在android6.0之后,SSLSocket.startHandshake只会读取系统预装的证书,而用户自己安装的第三方证书是不会读取的,这是因为google增加的安全机制导致的,而我在测试的时候用的是自己安装的证书,并且设备是android 7.0的,导致使用okhttp不能访问https。

重要的结论这里再说一遍

By default, secure connections (usingprotocols like TLS and HTTPS) from all apps trust the pre-installed system CAs,and apps targeting Android 6.0 (API level 23) and lower also trust theuser-added CA store by default.

Which means that on Android Nougat(7.0), the game for CAs changed completely. If you have your key cert, you canadd a network security configuration file (if you have your cert), as describedhere: https://developer.android.com/training/articles/security-config.html

 

Or you can create your own TrustManager,as described here:https://developer.android.com/training/articles/security-ssl.html#SelfSigned


问题的解决办法很简单,修改Androidmanifest.xml里面的targetSdk的APLLevel不大于23就行了。

你可能感兴趣的:(Android,https)