android自签名证书不会工作

时间:2016-07-11 07:23:04

标签: android ssl certificate self-signed

最近,我使用本教程在Apache Web服务器上制作了一个自我签名的证书:

http://theheat.dk/blog/?p=1023&cpage=1

Web服务需要打开证书。在浏览器中一切顺利。我导入了证书,网站将会打开。

我从rootCA.crt,client.crt,winter fell.crt制作了BKS文件,但没有人工作。
在Android中我得到

  

SSL3_GET_CLIENT_CERTIFICATE:peer没有返回证书No CAs   已知服务器验证?

apache日志中的

错误消息。

看来我的问题是关于发送到服务器的证书组合!在浏览器中我使用客户端和rootCA,如何将它们组合发送到webserver?

我的代码:

  try {
        DefaultHttpClient httpclient = new MyHttpClient(getApplicationContext());
        HttpGet get = new HttpGet("https://xxx.xxx.xxx.xxx/index.php");

        try {
            HttpResponse response = httpclient.execute(get);
        } catch (ClientProtocolException e) {
            System.out.println(e.getMessage());
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
        return "OK";


    } catch (Exception err) {
        return "Err";
    }

并且

public class MyHttpClient extends DefaultHttpClient {

final Context context;

public MyHttpClient(Context context) {
    this.context = context;
}

@Override
protected ClientConnectionManager createClientConnectionManager() {
    SchemeRegistry registry = new SchemeRegistry();
    // Register for port 443 our SSLSocketFactory with our keystore
    // to the ConnectionManager
    registry.register(new Scheme("https", newSslSocketFactory(), 443));
    return new SingleClientConnManager(getParams(), registry);
}

private SSLSocketFactory newSslSocketFactory() {
    try {
        // Get an instance of the Bouncy Castle KeyStore format
        KeyStore trusted = KeyStore.getInstance("BKS");
        // Get the raw resource, which contains the keystore with
        // your trusted certificates (root and any intermediate certs)
        InputStream in = context.getResources().openRawResource(R.raw.comb);
        try {
            // Initialize the keystore with the provided trusted certificates
            // Also provide the password of the keystore
            trusted.load(in, "mysecret".toCharArray());
        } finally {
            in.close();
        }

        // Pass the keystore to the SSLSocketFactory. The factory is responsible
        // for the verification of the server certificate.
        SSLSocketFactory sf = new SSLSocketFactory(trusted);
        // Hostname verification from certificate
        // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
        //sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        return sf;
    } catch (Exception e) {
        throw new AssertionError(e);
    }
}

你的帮助真的很感激!

1 个答案:

答案 0 :(得分:1)

使用以下给定的自定义SSLSocketFactory类。

public class AndroidSSLSocketFactory extends SSLSocketFactory {
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(
            "X509");
    public AndroidSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);
        tmf.init(truststore);
        TrustManager[] trustManagers = tmf.getTrustManagers();
        final X509TrustManager origTrustmanager = (X509TrustManager)trustManagers[0];
        TrustManager tm = new X509TrustManager() {
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return origTrustmanager.getAcceptedIssuers();
            }

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

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] chain, String authType)
                    throws CertificateException {
                origTrustmanager.checkServerTrusted(chain, authType);
            }
        };
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{tm}, null);
    }
}

此类通过X509证书管理服务器和Android之间的传输层安全性。

newSslSocketFactory()方法中使用它。替换

SSLSocketFactory sf = new SSLSocketFactory(trusted);

使用

SSLSocketFactory sf = new AndroidSSLSocketFactory(trusted);

希望这会对你有所帮助。

  

信息: - HttpClient已弃用于Android 6.0,您应该使用HttpURLConnection代替。Link

更新1: - 根据{{​​3}}链接,以便使用自签名证书您可以创建自己的TrustManager。因此,在TrustManager代码中进行更改。这可能有助于未来的用户。