今天在与后台服务器调试时,因为使用了https,在Android 6.0以上的手机上面连接正常,在Android 6.0以下的手机出现了下面的异常,导致连接服务器失败:
com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
这是因为,在Android 6.0之后,Google 采用用BoringSSL 代替了OpenSSL ,所以导致6.0之前的系统和6.0之后的系统在使用https时出现了不一致的情况,经过网上资料查询之后,找到了一种靠谱的方案,虽然报错的信息不一样,但是原因是一样,亲测可用,分享给大家:
原文地址:https://blog.csdn.net/rnzuozuo/article/details/52314617
我是使用了Volley,可以在进行StringRequest之前设置一个X509TrustManager。
首先新建一个类FakeX509TrustManager:
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class FakeX509TrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new
X509Certificate[] {};
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
//To change body of implemented methods use File | Settings | File Templates.
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] x509Certificates, String s) throws java.security.cert.CertificateException {
//To change body of implemented methods use File | Settings | File Templates.
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
// TODO Auto-generated method stub
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[] { new FakeX509TrustManager() };
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
}
}
然后在进行StringRequest之前设置:
FakeX509TrustManager.allowAllSSL();
mStringRequest = new StringRequest(Request.Method.POST,
url,
getDefaultSuccessListener(),
mErrorListener){
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return params;
}
};
mRequestQueue.add(mStringRequest);
再次运行则发现可以正常获取数据。
可以加一个判断,当android版本低于6.0的时候,才调用FakeX509TrustManager.allowAllSSL() 此方法。