Android 4.0- 4.4 不支持TLS v1.1 和TLS v1.2

来源:互联网 发布:宣城太守知不知 编辑:程序博客网 时间:2024/05/16 13:50
上周后台前置更换了通讯协议为TLV1.2 后,导致客户端android 4.0-4.4系统的手机无法正常登录app, 但是android 5.0以上可以正常使用。
真机测试后发现,android studio报一下的错:
W/ System err:Cause by : javax.net.ssl.SSLProtocolException: SSL handshake aborted:ssl=0x7675477: Failure in SSL library,usually a protocol error
W/ System err:ERROR:14077402e:SSL routines: SSL23_GET_SERVER_HELLO: tlsv1 alert protocol version(external/openssl/ssl/s23_clnt.c:744 ox7423cd74:0x00000000)

网上好多都是教自定义SSLSocketFactory 去创建SSL链接,是使用javax.net.ssl.SSLSocketFactory,而这里是使用org.apache.http.conn.ssl.SSLSocketFactory,通讯组件是用httpClient.

解决办法:
*******************************************************************************************************
importjava.io.IOException;
importjava.net.Socket;
importjava.net.UnknownHostException;
importjava.security.KeyManagementException;
importjava.security.KeyStore;
importjava.security.KeyStoreException;
importjava.security.NoSuchAlgorithmException;
importjava.security.UnrecoverableKeyException;

importjavax.net.ssl.SSLContext;
importjavax.net.ssl.SSLSocket;
importjavax.net.ssl.TrustManager;
importjavax.net.ssl.X509TrustManager;

importorg.apache.http.conn.ssl.SSLSocketFactory;

public classSSLSocketFactoryEx extends SSLSocketFactory {

SSLContextsslContext= SSLContext.getInstance("TLS");
publicSSLSocketFactoryEx(KeyStore truststore)
throwsNoSuchAlgorithmException, KeyManagementException,
KeyStoreException, UnrecoverableKeyException {
super(truststore);
TrustManager tm =new X509TrustManager() {
publicjava.security.cert.X509Certificate[] getAcceptedIssuers() {return null;}
@Override
public voidcheckClientTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throwsjava.security.cert.CertificateException {}
@Override
public voidcheckServerTrusted(
java.security.cert.X509Certificate[] chain, String authType)
throwsjava.security.cert.CertificateException {}
};
sslContext.init(null,new TrustManager[] { tm }, null);
}

@Override
publicSocket createSocket(Socket socket, String host,int port,booleanautoClose) throwsIOException, UnknownHostException {

returnenableTLSOnSocket(sslContext.getSocketFactory().createSocket(socket, host, port,autoClose));
}

@Override
publicSocket createSocket() throws IOException {

returnenableTLSOnSocket(sslContext.getSocketFactory().createSocket());
}

privateSocket enableTLSOnSocket(Socket socket) {
((SSLSocket) socket).setEnabledProtocols(newString[] {"TLSv1.2","TLSv1.1"});
returnsocket;
}
}
****************************************************************************************************
//https无证书验证
KeyStore trustStore;
// 查看API这里可以得到一个默认的Type.
trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null,null);
// 这里发现需要一个KeyStore,那么我们就在上面New一个KeyStore,这是一个密钥库,查看API发现能直接 getInstance得到对象;
SSLSocketFactory sf =new SSLSocketFactoryEx(trustStore);
// 这里就是我们最需要的也是最关键的一步,设置主机认证,通过API发现有一个常量就是允许所有认证通过。
sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
//实现Httpprams的子类
HttpParams httpParams =new BasicHttpParams();
// 通过Http适配器设置必要参数,现在通用HTTP1.1协议,和UTF-8字符。
HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8);
//同样New出来,查看API,需要我们注册一个计划,来封装协议细节
SchemeRegistry registry =new SchemeRegistry();
// 既然是工具类,这里也把http协议加上,中间的协议工厂我们就用简单的PlainSocketFactory,这里可以通过API查看到,端口就用常用的80端口(默认)
registry.register(newScheme("http", PlainSocketFactory.getSocketFactory(),80));
// 最后一个参数是端口设置,Https常用的端口就是443
registry.register(newScheme("https", sf,443));
//ClientConnectionManager是一个借口,就实现他的子类,同样需要2个参数,第一个我们熟悉,第二个就是让我们自定义自己的一套方案协议,继续在上面一步一步完成;
ClientConnectionManager ccm =new ThreadSafeClientConnManager(httpParams, registry);
//返回我们需要的一个默认Httpclient,为了把之前做的关联起来,就new最多参数的构造函数,需要2个参数,Httpparams是我们熟悉的,
//发现ClientConnectionManager不太熟悉,通过API发现这是客服端连接管理者,既然这样,就在上面一步一步完成。
httpClient= newDefaultHttpClient(ccm, httpParams);

***************************************************************************************************
注意:android sdk23以上不支持httpClient, 解决办法可以上网搜索以下。