Android Volley使用Https与服务器连接失败的解决方案

今天在与后台服务器调试时,因为使用了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() 此方法。

发布了27 篇原创文章 · 获赞 24 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/shving/article/details/88559199