我正在构建一个使用Retrofit和自定义Okhttp客户端通过httpS获取一些JSON数据的应用程序.它可以在KitKat上正常工作.一旦我转到Android 5、6或7,SSL握手就会失败.
服务器支持TLSv1,仅此一项.它还使用古老的,过期的,自签名证书.使用qualys的SSL工具进行了测试,该工具告诉我所有版本的AndroID都可以连接.这是我得到的:
Okhttp客户端:
public class httpClIEnt {public static OkhttpClIEnt getUnsafeOkhttpClIEnt() { try { // Create a trust manager that does not valIDate certificate chains final TrustManager[] trustAllCerts = new TrustManager[] { new x509trustmanager() { @OverrIDe public voID checkClIEntTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @OverrIDe public voID checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @OverrIDe public java.security.cert.X509Certificate[] getAcceptedissuers() { return new java.security.cert.X509Certificate[]{}; } } }; // Install the all-trusting trust manager final SSLContext sslContext = SSLContext.getInstance("TLSv1"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); // Create a ssl socket factory with our all-trusting manager final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); //URL url = new URL(APIIntentService.getHostAddress()); //final SSLSocketFactory sslSocketFactory = new NoSSLv3SocketFactory(url);// Connectionspec spec = new Connectionspec.Builder(Connectionspec.COMPATIBLE_TLS)// .tlsversions(Tlsversion.TLS_1_0)// .cipherSuites(// CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,// CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,// CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,// CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,// CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,// CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,// CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,// CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,// CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,// CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA)// .build();// String hostname = "API.server.domain";// CertificatePinner certificatePinner = new CertificatePinner.Builder()// .add(hostname, "sha256/3Iiwgs3a0qjPCnBQzW/GeHhPbZvhaJtxKvMJJVO5KdU=")// .build(); final OkhttpClIEnt.Builder builder = new OkhttpClIEnt.Builder();// builder.connectionspecs(Collections.singletonList(spec));// builder.certificatePinner(certificatePinner); builder.sslSocketFactory(sslSocketFactory); builder.hostnameVerifIEr(new HostnameVerifIEr() { @OverrIDe public boolean verify(String hostname, SSLSession session) { return true; } }); builder.authenticator(new Authenticator() { @OverrIDe public Request authenticate(Route route, Response response) throws IOException { String credential = Credentials.basic("user", "pass"); return response.request().newBuilder() .header("Authorization", credential) .build(); } }); OkhttpClIEnt okhttpClIEnt = builder.build(); return okhttpClIEnt; } catch (Exception e) { throw new RuntimeException(e); }}
我知道此代码在安全性方面是多么可怕.我的主管要求这样做.我告诉他这有多严重.
我已经尝试了两种方法来解决我的问题,它们在那段代码中已被注释掉-证书固定和请求TLSv1以及特定的密码列表.在其他问题中找到了这两个,但是它们什么也没改变(堆栈跟踪完全相同).
堆栈跟踪
以下是堆栈跟踪的有趣内容:
I/RETROFIT: Data retrIEval Failed! javax.net.ssl.SSLHandshakeException: Handshake Failed*sniP*Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0xb43eb200: Failure in SSL library, usually a protocol errorerror:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:770 0xac6fedd4:0x00000000) at com.androID.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
似乎AndroID突然尝试使用SSLv3,但Wireshark显示通过TLSv1的通信.它以应有的客户端Hello开头,但是服务器会立即以握手失败响应(40).
因为我全都没主意,所以极大地感谢了所有帮助.请要求是否需要澄清.
谢谢.
解决方法:
告诉主管,您的http客户端无法连接到严重不安全的httpS服务器.您可以说这是计算机的限制,唯一的选择是更新服务器.
完成后,您可以添加仅开发调试模式.为此,请启用服务器支持的密码套件.您可以从qualys工具中获取列表.
总结以上是内存溢出为你收集整理的改进:在API21设备上启动时,Android应用失败了SSL握手全部内容,希望文章能够帮你解决改进:在API21设备上启动时,Android应用失败了SSL握手所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)