新浪微博请求数据出错(Android Volley Https证书不信任)的解决方案

今天在调用新浪微博android sdk时出现Https证书不信任的问题,查了很多资料终于解决了,在这里把解决方案分享给大家。

错误如下:

javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature

具体错误如下:

com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
10-06 22:13:28.959: WARN/System.err(465): at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:133)
10-06 22:13:28.959: WARN/System.err(465): at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:105)
10-06 22:13:28.959: WARN/System.err(465): Caused by: javax.net.ssl.SSLHandshakeException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:477)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:328)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnection.setupSecureSocket(HttpConnection.java:185)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:433)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl$HttpsEngine.makeConnection(HttpsURLConnectionImpl.java:378)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.retrieveResponse(HttpURLConnectionImpl.java:1018)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getResponseCode(HttpURLConnectionImpl.java:726)
10-06 22:13:28.969: WARN/System.err(465): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:121)
10-06 22:13:28.969: WARN/System.err(465): at com.android.volley.toolbox.HurlStack.performRequest(HurlStack.java:109)
10-06 22:13:28.969: WARN/System.err(465): at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:93)
10-06 22:13:28.969: WARN/System.err(465): ... 1 more
10-06 22:13:28.979: WARN/System.err(465): Caused by: java.security.cert.CertificateException: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
10-06 22:13:28.979: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:161)
10-06 22:13:28.979: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:664)
10-06 22:13:28.979: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
10-06 22:13:28.979: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:474)
10-06 22:13:28.979: WARN/System.err(465): ... 10 more
10-06 22:13:28.979: WARN/System.err(465): Caused by: org.bouncycastle.jce.exception.ExtCertPathValidatorException: Could not validate certificate signature.
10-06 22:13:28.979: WARN/System.err(465): at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.processCertA(RFC3280CertPathUtilities.java:1504)
10-06 22:13:28.979: WARN/System.err(465): at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:293)
10-06 22:13:28.990: WARN/System.err(465): at java.security.cert.CertPathValidator.validate(CertPathValidator.java:197)
10-06 22:13:28.990: WARN/System.err(465): at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:156)
10-06 22:13:28.990: WARN/System.err(465): ... 13 more
10-06 22:13:28.990: WARN/System.err(465): Caused by: java.security.SignatureException: Signature was not verified
10-06 22:13:28.990: WARN/System.err(465): at org.apache.harmony.security.provider.cert.X509CertImpl.fastVerify(X509CertImpl.java:595)
10-06 22:13:28.990: WARN/System.err(465): at org.apache.harmony.security.provider.cert.X509CertImpl.verify(X509CertImpl.java:508)
10-06 22:13:28.990: WARN/System.err(465): at org.bouncycastle.jce.provider.CertPathValidatorUtilities.verifyX509Certificate(CertPathValidatorUtilities.java:1551)
10-06 22:13:28.990: WARN/System.err(465): at org.bouncycastle.jce.provider.RFC3280CertPathUtilities.processCertA(RFC3280CertPathUtilities.java:1496)
10-06 22:13:28.990: WARN/System.err(465): ... 16 more
10-06 22:13:28.999: WARN/System.err(465): java.lang.NullPointerException
10-06 22:13:28.999: WARN/System.err(465): at com.tsinghua.breakuphelper.network.BreakupClient$1.onErrorResponse(BreakupClient.java:44)
10-06 22:13:28.999: WARN/System.err(465): at com.android.volley.Request.deliverError(Request.java:517)
10-06 22:13:28.999: WARN/System.err(465): at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:101)
10-06 22:13:28.999: WARN/System.err(465): at android.os.Handler.handleCallback(Handler.java:587)
10-06 22:13:28.999: WARN/System.err(465): at android.os.Handler.dispatchMessage(Handler.java:92)
10-06 22:13:28.999: WARN/System.err(465): at android.os.Looper.loop(Looper.java:123)
10-06 22:13:28.999: WARN/System.err(465): at android.app.ActivityThread.main(ActivityThread.java:3683)
10-06 22:13:28.999: WARN/System.err(465): at java.lang.reflect.Method.invokeNative(Native Method)
10-06 22:13:28.999: WARN/System.err(465): at java.lang.reflect.Method.invoke(Method.java:507)
10-06 22:13:28.999: WARN/System.err(465): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-06 22:13:28.999: WARN/System.err(465): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-06 22:13:28.999: WARN/System.err(465): at dalvik.system.NativeStart.main(Native Method)

一番谷歌和百度之后,找到了两个很有用的链接:

腾讯微博oauth认证

http请求No peer certificate的解决方法

但是里面提出的解决方案都是针对自己实现HttpClient或者HttpURLConnection的,而我是使用了Google官方提供的Volley,如果要修改源码的话比较麻烦。于是我大胆猜测Volley底层是采用HttpURLConnection实现的,可以在进行StringRequest之前设置一个X509TrustManager。

首先新建一个类FakeX509TrustManager:

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 getParams() throws AuthFailureError {
                return params;
            }
	};
mRequestQueue.add(mStringRequest);

再次运行则发现可以正常获取数据。


如果大家觉得对自己有帮助的话,还希望能帮顶一下,谢谢:)
个人博客: http://blog.csdn.net/zhaoxy2850
本文地址: http://blog.csdn.net/zhaoxy_thu/article/details/12360473
转载请注明出处,谢谢!

你可能感兴趣的:(Android开发)