サーバー側から.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アクセス禁止アクセスを与えます。私は他の関連トピックを検索しましたが、実際にはそれらを読む前よりも深く混乱しています。回答をいただければ幸いです。
追加の詳細:
SSL構成をコーディングする場合は、指定されたP12ファイルを使用して、JKSに変換する必要はありません。また、JKSにコピーした証明書だけでなく、P12で秘密キーを使用する必要があります。これが直接あなたのニーズに合うかどうかはわかりませんが、これはあなたを正しい道に導くかもしれません:
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ファイルに証明書があることを確認することもできます。キーツールに関しては、参考のために、P12でkeytoolコマンドを実行できます(-storetype pkcs12を指定します)が、P12をJKSにインポートすることはできません。また、keytoolコマンドを使用してP12からキーのみをエクスポートすることもできません。
現時点では、このコードをテストするためのサーバーがセットアップされていないため、試してみて、まだ403エラーが表示されるかどうかを確認してください。
書くためにより多くのスペースが必要なので、これを答えとして追加します。
まず、質問:証明書は、Verisignなどの信頼できる機関によって署名されていますか?そうでない場合、トラストストアには、p12証明書を「有効」にするCA証明書(通常は.pemファイル)が必要です。デフォルトのJavaトラストストアには、VerisignやThawteなどの大企業からのCA証明書の大部分(すべてではないにしても)が含まれています。
また、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 はとても楽しいです。
これは私のために働いたものです:
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();
}
}
簡単なkeytoolコマンドは、.p12キーストアを.jksキーストアにエクスポートします。
keytool -importkeystore -srckeystore keystore.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore keystore.jks