我遇到了使用Java httpsurlconnection进行客户端证书认证的问题, 我尝试通过curl起作用(curl --request https://someurl --cert client_cert.pem --key client_key.pem --insecure),但是它不适用于Java, 我有2个证书-客户端和密钥。为客户端和密钥Pem文件创建了密钥库。
示例:: openssl pkcs12 -export -inkey client_key.pem -in client_cert.pem -out client.p12 -passout pass:Password123 -name test
我收到“找不到合适的证书-未经客户端身份验证即可继续”,请参见下文
[Raw read]: length = 5
0000: 16 03 03 00 04 .....
[Raw read]: length = 4
0000: 0E 00 00 00 ....
main, READ: TLSv1.2 Handshake, length = 4
check handshake state: server_hello_done[14]
update handshake state: server_hello_done[14]
upcoming handshake states: client certificate[11](optional)
upcoming handshake states: client_key_exchange[16]
upcoming handshake states: certificate_verify[15](optional)
upcoming handshake states: client change_cipher_spec[-1]
upcoming handshake states: client finished[20]
upcoming handshake states: server change_cipher_spec[-1]
upcoming handshake states: server finished[20]
ServerHelloDone
[read] MD5 and SHA1 hashes: len = 4
0000: 0E 00 00 00 ....
Warning: no suitable certificate found - continuing without client authentication
Certificate chain
package com.example.demo;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class HttpsUrlTest
{
final String KEYSTOREPATH = "c:\\test\\identity.p12";
final char[] KEYSTOREPASS = "Password123".toCharArray();
final char[] KEYPASS = "Password123".toCharArray();
public static void main(String args[])
{
try
{
HttpsUrlTest t1 = new HttpsUrlTest();
String httpsURL = "https://someurl/api/v1/details";
URL myUrl = new URL(httpsURL);
HttpsURLConnection conn = (HttpsURLConnection) myUrl.openConnection();
conn.setSSLSocketFactory(t1.getSSLFactories().getSocketFactory());
//conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.setReadTimeout(3000);
conn.setConnectTimeout(8 * 1000);
conn.setRequestMethod("GET");
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String text;
StringBuilder result = new StringBuilder();
while ((text = in.readLine()) != null)
result.append(text);
in.close();
System.out.println(result.toString());
}
catch(Exception e){
e.printStackTrace();
}
}
public SSLContext getSSLFactories()
{
try
{
InputStream storeStream = this.getClass().getResourceAsStream(KEYSTOREPATH);
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(storeStream, "Password123".toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, "Password123".toCharArray());
KeyManager[] keyManagers = keyFactory.getKeyManagers();
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManager[] tm = {new TrustAnyTrustManager() };
//SSLContext sslContext = SSLContext.getInstance("TLS"); // ("TLS", "SunJSSE");
//sslContext.init(null, tm, new java.security.SecureRandom());
sslContext.init(keyManagers, tm, new java.security.SecureRandom());
SSLContext.setDefault(sslContext);
return sslContext;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier
{
public boolean verify(String hostname, SSLSession session) {
return true;
}
}
private class TrustAnyTrustManager implements X509TrustManager
{
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException
{
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
}
}
}