1.6 (1.5 との互換性あり) でコンパイルされた署名付きアプレットがあり、いくつかの HTTPS が接続を取得します。
サーバー上の HTTPS 証明書は自己署名されていますが、アプレットは証明書チェーンを検証できるルート証明書を含む .pem ファイルを埋め込みます。
アプレットは、有効な商用証明書で署名されています。
私の単体テストでは、HTTPS 接続は問題なく行われています。
そして、この .pem import なしでは予想される接続エラーがあります:
javax.net.ssl.SSLHandshakeException - sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
しかし、Web サイトでアプレットを使用すると、HTTPS 接続が完了すると、次のセキュリティ警告ポップアップが表示されます。
[続行] をクリックしても [キャンセル] をクリックしても、HTTPS 接続は問題なく行われ、この警告は表示されなくなりました。
この役に立たないポップアップを削除する方法はありますか?
MANIFEST.MF内に、次を追加しました。
Trusted-Library: true
これも変更せずにテストしました:
Trusted-Only: true
Permissions: all-permissions
私のJavaコードは、ここからのコードのわずかに変更されたバージョンです:
InputStream pemStream = getClass().getResourceAsStream("/Resources/cacert.pem");
HttpsURLConnection con = (HttpsURLConnection) new URL(url).openConnection();
con.setSSLSocketFactory(getSocketFactoryFromPEM(pemStream));
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(false);
con.connect();
InputStream connectionStream = con.getInputStream();
private SSLSocketFactory getSocketFactoryFromPEM(InputStream pemStream) throws Exception
{
byte[] certAndKey = streamToBytes(pemStream);
byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(null);
keystore.setCertificateEntry("cert-alias", cert);
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context.getSocketFactory();
}
private static byte[] streamToBytes(InputStream fileStream) throws IOException
{
ByteArrayOutputStream ous = null;
try
{
byte[] buffer = new byte[4096];
ous = new ByteArrayOutputStream();
int read = 0;
while ((read = fileStream.read(buffer)) != -1)
ous.write(buffer, 0, read);
}
finally
{
try
{
if (ous != null)
ous.close();
}
catch (IOException e)
{
// swallow, since not that important
}
try
{
if (fileStream != null)
fileStream.close();
}
catch (IOException e)
{
// swallow, since not that important
}
}
return ous.toByteArray();
}
private static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter)
{
String data = new String(pem);
String[] tokens = data.split(beginDelimiter);
tokens = tokens[1].split(endDelimiter);
return DatatypeConverter.parseBase64Binary(tokens[0]);
}
private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException
{
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}
回避策 (2013 年 9 月 30 日)
Java コントロール パネルを使用して .pem を追加すると、セキュア サイト CA に Java ポップアップが表示されなくなります。
したがって、回避策は、.pem をプログラムでこのキー ストア (jsse cacerts) に追加することです。キーストアを正しい場所に格納するために
、関数getSocketFactoryFromPEMのコードを変更しました。
private SSLSocketFactory getSocketFactoryFromPEM(InputStream pemStream) throws Exception
{
byte[] certAndKey = streamToBytes(pemStream);
byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
X509Certificate cert = generateCertificateFromDER(certBytes);
KeyStore keystore = KeyStore.getInstance("JKS");
String userHome = System.getProperty("user.home");
String certPath = userHome + File.separator;
int os = getOperatingSystem();
switch (os)
{
case WINDOWS:
// <User Application Data Folder>\LocalLow\Sun\Java\Deployment\security\trusted.jssecacerts
certPath += "AppData" + File.separator + "LocalLow" + File.separator + "Sun" + File.separator + "Java" + File.separator + "Deployment";
break;
case MAC:
// ~/Library/Application Support/Oracle/Java/Deployment/security/trusted.jssecacerts
certPath += "Library" + File.separator + "Application Support" + File.separator + "Oracle" + File.separator + "Java" + File.separator + "Deployment";
break;
case LINUX:
// ${user.home}/.java/deployment/security/trusted.jssecacerts
certPath += ".java" + File.separator + "deployment";
break;
default:
break;
}
certPath += File.separator + "security" + File.separator + "trusted.jssecacerts";
File certInputFile = new File(certPath);
FileInputStream certInputStream = null;
if (certInputFile.canRead())
{
certInputStream = new FileInputStream(certInputFile);
keystore.load(certInputStream, null);
}
else
{
keystore.load(null);
}
keystore.setCertificateEntry("cert-alias", cert);
FileOutputStream certOutputFile = new FileOutputStream(certInputFile);
keystore.store(certOutputFile, "".toCharArray());
certOutputFile.close();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context.getSocketFactory();
}