(Java)未发送必需的SSL证书(在curl调用中使用时效果很好)

时间:2019-02-28 13:28:50

标签: java ssl ssl-certificate client-certificates

因此,我正在尝试通过在Java程序中使用客户端证书来测试与公司网络服务器的连接(使用2向SSL)。 我尝试在curl调用中使用相同的证书(分离的证书和密钥),并设法获得所需的响应。 但是,当我尝试在Java程序(组合为pkcs12格式)中使用它时,它给出了400响应,表明未发送任何必需的SSL证书。为什么会这样呢?

public static void main(String[] args) {
    System.out.println("Taufiq's mutual SSL-authentication test");
    org.apache.log4j.BasicConfigurator.configure();
    Logger.getRootLogger().setLevel(Level.INFO);

    try {
        final String CERT_ALIAS = "something", CERT_PASSWORD = "something";

        KeyStore identityKeyStore = KeyStore.getInstance("pkcs12");
        FileInputStream identityKeyStoreFile = new FileInputStream(new File("src/Cert.p12"));
        identityKeyStore.load(identityKeyStoreFile, CERT_PASSWORD.toCharArray());

        KeyStore trustKeyStore = KeyStore.getInstance("jks");
        FileInputStream trustKeyStoreFile = new FileInputStream(new File("src/truststore.jks"));
        trustKeyStore.load(trustKeyStoreFile, CERT_PASSWORD.toCharArray());

        SSLContext sslContext = SSLContexts.custom()
            // load identity keystore
            .loadKeyMaterial(identityKeyStore, CERT_PASSWORD.toCharArray(), new PrivateKeyStrategy() {
                @Override
                public String chooseAlias(Map<String, PrivateKeyDetails> aliases, Socket socket) {
                    return CERT_ALIAS;
                }
            })
            // load trust keystore
            .loadTrustMaterial(trustKeyStore, null)
            .build();

        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
            new String[]{"TLSv1.2", "TLSv1.1"},
            null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());

        CloseableHttpClient client = HttpClients.custom()
            .setSSLSocketFactory(sslConnectionSocketFactory)
            .build();

        // Call a SSL-endpoint
        callEndPoint (client);
    } catch (Exception ex) {
        System.out.println("Boom, we failed: " + ex);
        ex.printStackTrace();
    }
}

private static void callEndPoint(CloseableHttpClient aHTTPClient) {

    try {          
        String ServerUrl = "My Company URL";
        System.out.println("Calling URL: " + ServerUrl);
        HttpPost post = new HttpPost(ServerUrl);
        post.setHeader("Content-type", "application/json");

        System.out.println("**POST** request Url: " + post.getURI());

        HttpResponse response = aHTTPClient.execute(post);

        int responseCode = response.getStatusLine().getStatusCode();
        System.out.println("Response Code: " + responseCode);
        System.out.println("Content:-\n");
        BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
        String line;
        while ((line = rd.readLine()) != null) {
            System.out.println(line);
        }
    } catch (Exception ex) {
        System.out.println("Boom, we failed: " + ex);
        ex.printStackTrace();
    }

}

示例卷曲调用:     curl -v --key key.pem --pass ****** --cert cert.pem MyCompanyURL

2 个答案:

答案 0 :(得分:0)

我想您知道ssl握手如何工作。如果没有,请结识。然后使用Wireshark查看ssl握手。您将获得比某些该死的http库解释更好的ssl警报详细信息。如果有的话,这是一个误导性错误。

可以肯定的是,您的服务器必须信任您的客户端证书,因此我假设您首先正确设置了所有内容;您说您尝试过卷发,但没有说是否行得通。

最后,我无法识别这些SSL类,因此您将导入除jdk的jsse类之外的其他内容;您可能是该图书馆的受害者。

答案 1 :(得分:0)

事实证明,当我使用核心jdk jsse类时,程序运行正常。我使用上述程序是因为我是从互联网上复制示例之一。