服务器端给了我一个.p12
证书文件,我已经点击并安装在我的机器上,然后我可以通过浏览器访问HTTPS
站点。现在他们希望我用给出的证书抓取他们的网站。我陷入了它的第一阶段,试图从inputStream
获得httpsURLConnection
。该网站没有登录。它只检查您是否有证书。
到目前为止,我所做的是使用Firefox以.crt
文件格式导出证书。然后我使用keytool命令将它(.crt
文件,而不是.p12
)导入java密钥库。然后在代码中:
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
File ksFile = new File(keystorePath);
in = new FileInputStream(ksFile);
ks.load(in, "changeit".toCharArray());
X509Certificate cert = (X509Certificate) ks.getCertificate(certificateAlias);
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HttpsURLConnection con = (HttpsURLConnection) (new URL(urlString)).openConnection();
con.connect();
con.getInputStream();
con.disconnect();
getInputStream()
会给我403错误禁止访问。我搜索了其他相关主题,实际上比阅读之前更加困惑。非常感谢答案。
其他详情:
答案 0 :(得分:31)
如果您想尝试编写SSL配置代码,可以使用提供给您的P12文件,而无需将其转换为JKS。此外,您需要使用P12中的私钥,而不仅仅是您复制到JKS中的证书。不确定这是否能直接满足您的需求,但这可能会让您走上正确的道路:
KeyStore clientStore = KeyStore.getInstance("PKCS12");
clientStore.load(new FileInputStream("test.p12"), "testPass".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientStore, "testPass".toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
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();
SSLContext sslContext = null;
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kms, tms, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
URL url = new URL("https://www.testurl.com");
HttpsURLConnection urlConn = (HttpsURLConnection) url.openConnection();
以这种方式配置trustStore是可选的。您可以使用P12链中的所有证书创建一个JKS,或者只是确保它们在您的JRE的cacerts文件中。至于keytool,作为参考,您可以在P12上运行keytool命令(指定-storetype pkcs12),但不能将P12导入JKS。您也无法使用keytool命令从P12导出密钥。
我目前没有设置服务器来测试这段代码,所以试试看是否仍然收到403错误。
答案 1 :(得分:4)
将此作为答案添加,因为我需要更多空间来编写。
首先,一个问题:证书是否由Verisign等受信任的机构签署?如果不是,则信任库应具有CA证书(通常为.pem文件),这使得p12证书“有效”。默认的Java信任库包含来自大公司的大多数(如果不是全部)CA证书,例如Verisign和Thawte。
此外,您可以测试您的应用程序以连接到安全服务器而无需编码SSL配置,但使用一些命令行参数,例如:
java -Djavax.net.ssl.keyStore=[path_to_p12_cert] \
-Djavax.net.ssl.keyStorePassword=[p12_password] \
-Djavax.net.ssl.keyStoreType=PKCS12 \
-Djavax.net.ssl.trustStore=[path_to_trust_store_with_CA_certificates] \
-Djavax.net.ssl.trustStorePassword=[trust_store_password] \
[MainClass]
然后你的代码就变成了
HttpsURLConnection con = (HttpsURLConnection) (new URL(urlString)).openConnection();
con.connect();
con.getInputStream();
con.disconnect();
如果你感到自虐,JSSE ref guide非常有趣。
答案 2 :(得分:3)
这对我有用:
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("client-p12-keystore.p12"));
try {
keyStore.load(instream, "password".toCharArray());
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "password".toCharArray())
//.loadTrustMaterial(trustStore, new TrustSelfSignedStrategy())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSSLSocketFactory(sslsf)
.build();
try {
HttpGet httpget = new HttpGet("https://localhost:8443/secure/index");
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
System.out.println("----------------------------------------");
System.out.println(response.getStatusLine());
if (entity != null) {
System.out.println("Response content length: " + entity.getContentLength());
}
EntityUtils.consume(entity);
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
答案 3 :(得分:1)
如果您使用的是Spring,可以通过RestTemplate进行访问:
public RestTemplate restTemplate() throws Exception {
KeyStore clientStore = KeyStore.getInstance("PKCS12");
InputStream resource = this.getClass().getClassLoader().getResourceAsStream("path_to_certificate.p12");
clientStore.load(resource, "p12_password".toCharArray());
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
sslContextBuilder.setProtocol("TLS");
sslContextBuilder.loadKeyMaterial(clientStore, "p12_password".toCharArray());
sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy());
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContextBuilder.build());
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLSocketFactory(sslConnectionSocketFactory)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
答案 4 :(得分:0)
简单的keytool命令会将.p12密钥库导出到.jks密钥库:
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks