在android应用程序中配置SSL客户端证书,在tomcat上的Web服务器中进行客户端身份验

时间:2014-07-08 10:24:03

标签: android apache tomcat ssl client-server

我在我的计算机上本地安装了apache服务器并运行。我开始使用SSL服务器证书进行服务器身份验证为此,我将tomcat和server证书的server.xml文件的服务器密钥库路径添加到android app中的SSL上下文信任库。它工作得非常好。

现在我需要为客户端身份验证配置相同的内容。为此,我创建了一个客户端密钥库,并将该密钥库存储在android app的resources / raw文件夹中,并将其放入android app的密钥库中。

我使用以下命令为服务器和客户端创建了密钥库。

keytool -genkey -alias server -keyalg RSA -keystore server.jks
keytool -genkey -alias client -keyalg RSA -keystore client.jks
keytool -export -file server.cert -keystore server.jks -storepass password -alias server
keytool -export -file client.cert -keystore client.jks -storepass password -alias client

所以我创建了2个密钥库,一个用于客户端,另一个用于服务器,client.jks和server.jks。我有从相应的密钥库导出的client.cer和server.cer证书。

用于配置SSL上下文的客户端(Android应用程序代码)。我已将client.jks和server.cer文件存储在res / raw文件夹中,并在下面的代码中引用它。

public HttpClient myHttpsClient() {
    HttpClient client = null;
    char[] passphrase = "password".toCharArray();

    try {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        CertificateFactory clientcf = CertificateFactory.getInstance("X.509");
        InputStream caInput = context.getResources().openRawResource(R.raw.server);
        InputStream clientcert = context.getResources().openRawResource(R.raw.client);
        Certificate ca;
        Certificate clientca;
        try {
            clientca = clientcf.generateCertificate(clientcert);
            ca = cf.generateCertificate(caInput);
            System.out.println("ca="+ ((X509Certificate) ca).getSubjectDN());
        } finally {
            caInput.close();
            clientcert.close();
        }
        String keyStoreType = KeyStore.getDefaultType();
        KeyStore keyStoreclient = KeyStore.getInstance(keyStoreType);
        keyStoreclient.load(null, null);
        keyStoreclient.setCertificateEntry("ca", clientca);


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



        String kmfAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(kmfAlgorithm);
            kmf.init(keyStoreclient,passphrase);



        // 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 context = SSLContext.getInstance("TLS");
        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

        MySSLSocketFactory socketFactory = new MySSLSocketFactory(context);//,new BrowserCompatHostnameVerifier());

        client = createHttps(socketFactory);
    } catch (Exception e) {
        e.printStackTrace();
    }

    return client;

现在服务器配置如下。

<Connector SSLEnabled="true" acceptCount="100" clientAuth="false" truststoreFile="/Users/prabhuraj/client.cer" 
truststorePass="password" disableUploadTimeout="true" enableLookups="false" maxThreads="25"
port="8443" keystoreFile="/Users/prabhuraj/server.jks" keystorePass="password"
protocol="org.apache.coyote.http11.Http11NioProtocol" scheme="https"
secure="true" sslProtocol="TLS" />

完成上述配置后。 SSL握手失败。有人可以告诉我是否配置错误?提前致谢。

1 个答案:

答案 0 :(得分:1)

您没有使用KeyManagerFactory初始化SSLContext

变化:

context.init(null, tmf.getTrustManagers(), null);

context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

但是,用于客户端身份验证的证书将需要它的私钥。请看这篇文章的解释:https://stackoverflow.com/a/11199270/2762154