由于这两个线程,我发现了如何做到这一点:
如何
使用 opensc pkcs#11 提供程序从 Java java keytool 中的 usb 令牌获取 KeyStore 仅适用于启用调试选项
还有这个网站:
在 java 中使用 eToken 进行 PDF 签名
首先,如果网站有一个默认情况下 java 不信任的证书,您必须创建一个 trustStore 并将其加载到 java 的系统属性中。你可以在这里看到如何做到这一点:
Oracle - 生成 KeyStore 和 TrustStore(使用 keytool)
您必须找到用于您的智能卡/eToken 的 PKCS#11 库在您的计算机中的安装位置,在我的计算机中它位于“C:\Windows\System32\eTPKCS11.dll”中。然后像这样创建一个 .cfg 文件:
name=SafeNet
library=C:\Windows\System32\eTPKCS11.dll
slot=4
你在哪里给它一个名字和你的 PKCS#11 库的路径。Slot 是连接您的 eToken/SmartCard 的插槽(如果您不想要,则无需设置)。
现在我的代码如下所示:
System.setProperty("javax.net.ssl.trustStore", "cfgFiles/trustedHttpsCertificates.truestore");
System.setProperty("javax.net.ssl.trustStoreType", "jks");
System.setProperty("javax.net.ssl.trustStorePassword", "oiadad");
Provider newProvider = new SunPKCS11("cfgFiles/etpkcs11.cfg");
Security.addProvider(newProvider);
try {
KeyStore keyStore = KeyStore.getInstance("PKCS11");
keyStore.load(null, "".toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore,null);
SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
sslContext.init(keyFactory.getKeyManagers(), null, null);
sslSocketFactory = sslContext.getSocketFactory();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (UnrecoverableKeyException e1) {
e1.printStackTrace();
} catch (KeyManagementException e1) {
e1.printStackTrace();
}
我首先告诉 java 在哪里寻找我的 trustStore。然后我将路径传递给我的 cfg 文件,用它创建一个提供程序并告诉安全这个新提供程序存在。
在此之后,我初始化并加载一个 PKCS11 KeyStore,给它一个空白密码(如果我愿意,可以传递我的真实密码,但是这样会出现一个 SafeNet 弹出窗口并询问我的密码)。
然后我实例化一个 KeyManagerFactory 和一个 SSLSocketFactory。这是使用 eToken 访问多重身份验证 https url 的最后一步。
现在,访问受保护的 https 网站还有一个技巧,您必须为 HttpsURLConnection 提供新的 SSLSocketFactory。你可以这样做:
try {
HttpsURLConnection conn = (HttpsURLConnection)new URL(<your-https-url-here>).openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setSSLSocketFactory(sslSocketFactory);
int responseCode = conn.getResponseCode();
System.out.println("RESPONSE: " + responseCode);
InputStream inputstream = conn.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String line = null;
String htmlResponse = "";
while ((line = bufferedreader.readLine()) != null) {
htmlResponse += line + "\n";
//System.out.println("html: " + line);
}
} catch (ProtocolException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
我希望这可以帮助任何遇到电子令牌或智能卡问题的人。