如何在Android 4.1+上将自签名SSL证书导入Volley

时间:2014-02-25 16:46:33

标签: android ssl ssl-certificate x509certificate android-volley

我开发使用 Volley 的android应用程序。 所有通信都通过 HTTPS 连接完成。 因为我在本地环境中测试它,所以我使用Tomcat的自签名证书。

之前,我只有android 2.3 3.0 设备。现在我还 4.1和4.4

我的实现使用此方法:http://developer.android.com/training/articles/security-ssl.html(部分未知的证书颁发机构) 在Android 高达4.1 的设备上,它可以完美运行。带有自定义证书的SSLSocketFactory传递给Volley:

Volley.newRequestQueue(getApplicationContext(), new HurlStack(null, socketFactory));

但Android 4.1+会发生什么? 为什么它不起作用? 我也尝试使用 NullX509TrustManager

private static class NullX509TrustManager implements X509TrustManager {
    @Override
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
            throws CertificateException {
    }

    @Override
    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

但它仍然不起作用......

4 个答案:

答案 0 :(得分:3)

我已经用这里提到的解决方案解决了这个问题:

http://developer.android.com/training/articles/security-ssl.html

主机名验证的常见问题

添加自定义主机名验证程序,在Volley项目中为我的主机名返回true并编辑HurlStack openConnection方法:

if ("https".equals(url.getProtocol()) && mSslSocketFactory != null) {            
    ((HttpsURLConnection)connection).setSSLSocketFactory(mSslSocketFactory);
    ((HttpsURLConnection)connection).setHostnameVerifier(new CustomHostnameVerifier());         
}

答案 1 :(得分:0)

如果您已经有一个 .crt 文件,并希望将其附加到 Volley ,则可以按照以下两个简单步骤进行操作。

第1步:将此方法写入您的代码。

public SSLSocketFactory getSocketFactory(Context context)
        throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {

    // Load CAs from an InputStream (could be from a resource or ByteArrayInputStream or ...)
    CertificateFactory cf = CertificateFactory.getInstance("X.509");

    InputStream caInput = new BufferedInputStream(context.getResources().openRawResource(R.raw.myFile));
                                                   // I paste my myFile.crt in raw folder under res.
    Certificate ca;

    //noinspection TryFinallyCanBeTryWithResources
    try {
        ca = cf.generateCertificate(caInput);
        System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
    } finally {
        caInput.close();
    }

    // Create a KeyStore containing our trusted CAs
    String keyStoreType = KeyStore.getDefaultType();
    KeyStore keyStore = KeyStore.getInstance(keyStoreType);
    keyStore.load(null, null);
    keyStore.setCertificateEntry("ca", ca);

    // Create a TrustManager that trusts the CAs in our KeyStore
    String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
    tmf.init(keyStore);

    // Create an SSLContext that uses our TrustManager
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, tmf.getTrustManagers(), null);

    return sslContext.getSocketFactory();
}

第2步:在使用Volley进行任何请求之前,只需将以下内容添加到此行即可。

HttpsURLConnection.setDefaultSSLSocketFactory(getSocketFactory(context));

Android Studio会要求您在try / catch中将该行括起来,以获取我们方法抛出的所有异常。所以就让它做。

快乐编码!

答案 2 :(得分:-1)

我找到的最简单的方法是adding this class并从new NukeSSLCerts().nuke(); 方法

执行它
#include <iostream>
using namespace std;

void main()
{
    //Initial array input
    int state_array[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 };
    int temp[1] = { 0 };

    int array_size = sizeof(state_array) / (sizeof(temp[0]));

    for (int i = 0; i<65535; i++)
    {
        temp[0] = state_array[15];

      //XOR Values
        for (int j = 0; j<16; j++) {
            if ((j == 2 || j == 3 || j == 5) && state_array[15] == 1) {
                state_array[j] = !state_array[j];
            }
        }

        //Shift values
        for (int j = array_size-1; j>0; j--)
        {
            if (j == 0) {
                state_array[0] = temp[0];
            }
            else {
                state_array[j] = state_array[j-1];
            }
        }
    }
}

它将使凌空信任所有SSL证书

答案 3 :(得分:-1)

信任所有SSL证书: - 如果要在测试服务器上进行测试,可以绕过SSL。 但是不要将此代码用于生产。

public static class NukeSSLCerts {
protected static final String TAG = "NukeSSLCerts";

public static void nuke() {
    try {
        TrustManager[] trustAllCerts = new TrustManager[] { 
            new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    X509Certificate[] myTrustedAnchors = new X509Certificate[0];  
                    return myTrustedAnchors;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] certs, String authType) {}

                @Override
                public void checkServerTrusted(X509Certificate[] certs, String authType) {}
            }
        };

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String arg0, SSLSession arg1) {
                return true;
            }
        });
    } catch (Exception e) { 
    }
}

}

请在Activity或您的Application Class中的onCreate()函数中调用此函数。

NukeSSLCerts.nuke();

这可以用于Android中的Volley。 更多参考 https://newfivefour.com/android-trust-all-ssl-certificates.html