如何使用 Java 在 https 连接请求中附加 .pfx 证书?
How to attach .pfx certificate in https connection request using Java?
我有一个安装在 Windows 证书存储中的 pfx 证书,我可以使用 C# 将其附加到 https rest 调用中。
现在我需要使用 Java 做同样的事情。我读到 .pfx 证书有私钥以及一个或多个证书。
我收到以下错误:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径。
我在 Java
中尝试过的事情
我直接使用 KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI") 从 Windows 商店获取证书并创建了一个 SSLContext我在 HTTPS 调用中使用的
我从 Windows 存储中导入证书作为 .cer 文件并从代码中读取它作为文件并将其附加到 https 调用
我从代码中读取了 .pfx 文件并将其附加到调用中。
我已将证书添加到 Java-Home (C:/Work/certi/jre1.8.0_91/lib/security/cacerts) 的 cacerts 文件中,使用KeyTool.
完整的Java代码如下
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
public class TestElk {
public static void main(String[] args) throws ClientProtocolException, IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException, NoSuchProviderException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certificateFactory.generateCertificate(new FileInputStream(new File("C:/Work/certi/jre1.8.0_91/lib/security/elkcert.cer")));//exported certificate
/* KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null,null);
Enumeration enumeration = ks.aliases();
while(enumeration.hasMoreElements()) {
String alias = (String)enumeration.nextElement();
System.out.println("alias name: " + alias); }
Certificate[] certificate = ks.getCertificateChain("alias");
*/
// Create TrustStore
KeyStore trustStoreContainingTheCertificate = KeyStore.getInstance(KeyStore.getDefaultType());
trustStoreContainingTheCertificate.load(null, null);
trustStoreContainingTheCertificate.setCertificateEntry("cert", certificate);
// Create SSLContext
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStoreContainingTheCertificate);
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null,trustManagerFactory.getTrustManagers(),new SecureRandom());
SSLContext.setDefault(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
URL url = new URL("https://server-link");
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
con.setConnectTimeout(10000);
con.setSSLSocketFactory(sslContext.getSocketFactory());
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
System.out.println(sb.toString());
//int s= con.getResponseCode(); }
假设您已将 Issuing CA Cert(参见下面的评论)导入到 cacerts 文件,以下内容应该有效,可以在不同的 SO 线程中找到很多帮助 Here:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
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.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
public class TestElk {
public static void main(String[] args) throws ClientProtocolException, IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException, NoSuchProviderException {
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream(new File("C:/path_to_pfx/mypfx.pfx")), "pfxPass".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, "pfxPass".toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
// Assuming that you imported the CA Cert "Subject: CN=MBIIS CA, OU=MBIIS, O=DAIMLER, C=DE"
// to your cacerts Store.
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("cacerts"), "changeit".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] tms = tmf.getTrustManagers();
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms,tms,new SecureRandom());
SSLContext.setDefault(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
System.setProperty("https.proxyHost", "IP_OF_PROXY_HOST_GOES_HERE");
System.setProperty("https.proxyPort", "PORT_NUMBER_GOES_HERE");
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
URL url = new URL("https://server-link");
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
con.setConnectTimeout(10000);
con.setSSLSocketFactory(sslContext.getSocketFactory());
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
System.out.println(sb.toString());
//int s= con.getResponseCode();
}
}
我有一个安装在 Windows 证书存储中的 pfx 证书,我可以使用 C# 将其附加到 https rest 调用中。
现在我需要使用 Java 做同样的事情。我读到 .pfx 证书有私钥以及一个或多个证书。
我收到以下错误:PKIX 路径构建失败:sun.security.provider.certpath.SunCertPathBuilderException:无法找到请求目标的有效证书路径。
我在 Java
中尝试过的事情我直接使用 KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI") 从 Windows 商店获取证书并创建了一个 SSLContext我在 HTTPS 调用中使用的
我从 Windows 存储中导入证书作为 .cer 文件并从代码中读取它作为文件并将其附加到 https 调用
我从代码中读取了 .pfx 文件并将其附加到调用中。
我已将证书添加到 Java-Home (C:/Work/certi/jre1.8.0_91/lib/security/cacerts) 的 cacerts 文件中,使用KeyTool.
完整的Java代码如下
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
public class TestElk {
public static void main(String[] args) throws ClientProtocolException, IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException, NoSuchProviderException {
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
Certificate certificate = certificateFactory.generateCertificate(new FileInputStream(new File("C:/Work/certi/jre1.8.0_91/lib/security/elkcert.cer")));//exported certificate
/* KeyStore ks = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
ks.load(null,null);
Enumeration enumeration = ks.aliases();
while(enumeration.hasMoreElements()) {
String alias = (String)enumeration.nextElement();
System.out.println("alias name: " + alias); }
Certificate[] certificate = ks.getCertificateChain("alias");
*/
// Create TrustStore
KeyStore trustStoreContainingTheCertificate = KeyStore.getInstance(KeyStore.getDefaultType());
trustStoreContainingTheCertificate.load(null, null);
trustStoreContainingTheCertificate.setCertificateEntry("cert", certificate);
// Create SSLContext
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStoreContainingTheCertificate);
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null,trustManagerFactory.getTrustManagers(),new SecureRandom());
SSLContext.setDefault(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
URL url = new URL("https://server-link");
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
con.setConnectTimeout(10000);
con.setSSLSocketFactory(sslContext.getSocketFactory());
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
System.out.println(sb.toString());
//int s= con.getResponseCode(); }
假设您已将 Issuing CA Cert(参见下面的评论)导入到 cacerts 文件,以下内容应该有效,可以在不同的 SO 线程中找到很多帮助 Here:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
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.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
public class TestElk {
public static void main(String[] args) throws ClientProtocolException, IOException, CertificateException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException, UnrecoverableKeyException, NoSuchProviderException {
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream(new File("C:/path_to_pfx/mypfx.pfx")), "pfxPass".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, "pfxPass".toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
// Assuming that you imported the CA Cert "Subject: CN=MBIIS CA, OU=MBIIS, O=DAIMLER, C=DE"
// to your cacerts Store.
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(new FileInputStream("cacerts"), "changeit".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustStore);
TrustManager[] tms = tmf.getTrustManagers();
final SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms,tms,new SecureRandom());
SSLContext.setDefault(sslContext);
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
System.setProperty("https.proxyHost", "IP_OF_PROXY_HOST_GOES_HERE");
System.setProperty("https.proxyPort", "PORT_NUMBER_GOES_HERE");
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection.setDefaultHostnameVerifier(hostnameVerifier);
URL url = new URL("https://server-link");
HttpsURLConnection con = (HttpsURLConnection)url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
con.setConnectTimeout(10000);
con.setSSLSocketFactory(sslContext.getSocketFactory());
con.connect();
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line+"\n");
}
br.close();
System.out.println(sb.toString());
//int s= con.getResponseCode();
}
}