我目前能够使用以下curl命令访问需要客户端证书的Web服务:
curl -k -v --cert ./certificate.pem https://api.com/unit
如何在Java应用程序中发出此请求?
请注意,我需要-k标志,它允许curl进行“不安全”的SSL连接。这也需要在Java应用程序中完成。
下面的代码提供了一个“sendSSLRequest”方法,该方法使用客户端SSL身份验证发送HTTP GET请求。
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.HttpGet;
public class SSLExample {
private final static String ENDPOINT_URL = "https://api.com/unit";
public void sendSSLRequest() {
final SSLContext sslContext = SSLContextLoader.initSSLContext();
final HttpClient client = HttpClients.custom()
.setSSLContext(sslContext)
.build();
final HttpGet request = new HttpGet(ENDPOINT_URL);
try {
client.execute(request);
} catch (final IOException e) {
//do some exception handling...
}
}
}
现在,SSLContext:你需要在某个地方初始化它。下面的“initSSLContext”方法将从给定的密钥库加载密钥材料,并从给定的信任库中加载信任材料(要信任的证书)。
public class SSLContextLoader {
private final static String clientKeyStorePath = "/path/to/client/keystore";
private final static String trustStorePath = "/path/to/truststore";
private final static String clientKeyStorePassword = "/password/for/client/keystore";
private final static String trustStorePassword = "/password/for/truststore";
private final static String keyPassword = "/passphrase/for/private/key";
public static SSLContext initSSLContext () {
try {
final KeyStore clientKeystore = KeyStore.getInstance("JKS");
clientKeystore.load(new FileInputStream(clientKeyStorePath), clientKeyStorePassword.toCharArray());
final KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream(trustStorePath), trustStorePassword.toCharArray());
final SSLContext sslContext = SSLContexts.custom()
.loadTrustMaterial(trustStore, null)
.loadKeyMaterial(clientKeystore, keyPassword.toCharArray())
.build();
return sslContext;
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return null;
}
}
关于-k选项,我邀请您查看以下问题/答案:Trusting all certificates using HttpClient over HTTPS。
此问题的最终解决方案是将服务器的证书包含在Java信任库中。
要下载并导入服务器的证书,我使用了来自GitHub的InstallCert Java代码
然后在系统属性中定义keyStore
和trustStore
,如下所示:
-Djavax.net.ssl.keyStore=/home/wildfly/key.pfx
-Djavax.net.ssl.keyStorePassword=xxxx
-Djavax.net.ssl=trustStore=$JAVA_HOME/jre/lib/security/cacerts
-Djavax.net.ssl.trustStorePassword=xxxx
-Djavax.net.ssl.keyStoreType=PKCS12"