如何请求需要客户端证书进行身份验证的URL

时间:2010-09-17 10:38:11

标签: java security url network-programming

我需要从使用客户端证书进行身份验证的服务器请求一个URL,但无法找到为我的应用程序执行此操作的方法。

我的问题是我正在处理的Java客户端有本地可用的证书文件,但是由于它将在其上运行的PC的限制,它无法在密钥库中安装证书。

简而言之,我只是希望能够明确指定用于我需要检索的URL的证书。

有什么建议吗?

2 个答案:

答案 0 :(得分:23)

目前尚不清楚你所谈论的限制是什么。更具体地说,我不确定您认为本地证书文件和密钥库之间的区别。大多数密钥库都是基于文件的,因此您可以直接以这种方式加载文件,而无需安装过程。这些限制是否与JVM本身使用的安全策略相关(这可能会阻止您实例化KeyStore)?

首先,它不仅仅是客户端所需的证书,而是其私钥。通常,人们在此上下文中使用“证书”一词来表示两者,但您确实需要确保您的文件不包含没有私钥的证书。通常,您会在PKCS#12文件(.p12 / .pfx)中找到私钥+证书的组合,许多工具以此格式导入/导出;它也是Sun JVM本身支持的密钥库格式(类型PKCS12)。

要使其工作,您需要配置与相应密钥库建立连接的内容。 SSL / TLS客户端证书身份验证始终由服务器启动:如果证书有证书(并且想要使用证书),则客户端会响应证书。要为特定URL配置它,您需要找出连接的原因(可能是HttpsURLConnection)并将其设置在那里(除非它在默认上下文中设置 - 即使它是在默认上下文中设置的,它只会用于请求它的服务器。)

要在JVM上全局设置密钥库(这可能是您的限制阻止您执行的操作),您可以设置javax.net.ssl.keyStore javax.net.ssl.keyStorePassword(及相关)系统属性。 (因为密码可见,所以最好不要在命令行上执行此操作。)

这些系统属性用于配置默认SSLContext(通常由HttpsURLConnection等库或类来透明地使用,以构建SSLSocketFactory然后{{ 1}},用这些属性初始化。)

您可以专门为您的文件构建SSLSocket以用于该连接。 SSLContext实际上是SSLContextSSLSocketFactory的工厂,您可以在给定的SSLEngine中设置SSLSocketFactory

以下将使用“/path/to/file.p12”构建HttpsURLConnection作为您的密钥库(即具有您的私钥和您要发送的证书的密钥库)并保留默认值信任库的设置(您还需要捕获输入流的异常)。

SSLContext

从那里你可以像这样配置连接(如果这是你正在使用的):

KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream("/path/to/file.p12");
ks.load(fis, "password".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "password".toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);

有些库可以让你直接传递HttpURLConnection connection = (HttpURLConnection) url.openConnection(); if (connection instanceof HttpsURLConnection) { ((HttpsURLConnection)connection) .setSSLSocketFactory(sc.getSSLSocketFactory()); } (Apache HTTP Client 4支持它,这可以通过Apache HTTP Client 3 using this完成。)

请注意,在加载密钥库时,您不需要提供密码作为直接参数,也可以使用回调(从GUI的角度来看可能更好)。

也许this library可以提供帮助(但没​​有必要):您可以使用KeystoreLoader为其帮助程序执行此操作。此库中还有SSLContextFactories(但您可能不需要任何包装器,因为它们往往用于自定义信任管理或密钥选择)。

这通常是如何配置客户端证书的,但是如果没有明确说明您的限制是什么(以及您正在使用哪些库),则很难提供更多详细信息。

答案 1 :(得分:1)

您可以在调用应用-Djavax.net.ssl.keystore=somefile时通过属性更改默认的JSSE密钥库。

因此,您可以使用keytool命令将证书导入密钥库并调用指向该密码库的应用程序,例如

keytool -importcert -file mycert -keystore mystore
java -Djavax.net.ssl.keystore=mystore ...