简体   繁体   English

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

[英]How to request a URL that requires a client certificate for authentication

I need to request a URL from a server that uses client certificates for authentication and can't find a way to do this for my application.我需要从使用客户端证书进行身份验证的服务器请求 URL,但找不到为我的应用程序执行此操作的方法。

My problem is that the Java client I'm working on has the certificate file available locally but due to restrictions on the PCs it will be running on it cannot install the certificate in a keystore.我的问题是我正在使用的 Java 客户端具有本地可用的证书文件,但由于将在其上运行的 PC 的限制,无法在密钥库中安装证书。

In short, I just want to be able to explicilty specify the certificate to use for the URL I need to retrieve.简而言之,我只想能够明确指定用于我需要检索的 URL 的证书。

Any suggestions?有什么建议吗?

It's not clear what the restrictions you're talking about are.目前还不清楚你所说的限制是什么。 More specifically, I'm not sure what you consider the difference between the local certificate file and a keystore.更具体地说,我不确定您认为本地证书文件和密钥库之间的区别是什么。 Most keystores are file-based, so you might be able to load the file this way directly, without needing an installation process.大多数密钥库都是基于文件的,因此您可以通过这种方式直接加载文件,而无需安装过程。 Are the restrictions related to the security policies used by the JVM itself (which may prevent you from instantiating KeyStore s)?这些限制是否与 JVM 本身使用的安全策略有关(这可能会阻止您实例化KeyStore )?

First, it's not just the certificate you need on the client side, but its private key.首先,它不仅仅是您在客户端需要的证书,而是它的私钥。 Often, people use the word "certificate" in this context to mean both, but you do need to make sure your file doesn't contain the certificate without the private key.通常,人们在此上下文中使用“证书”一词来表示两者,但您确实需要确保您的文件不包含没有私钥的证书。 Typically, you'll find the combination of private key + certificate in a PKCS#12 file (.p12/.pfx), a lot of tools import/export in this format;通常,您会在 PKCS#12 文件 (.p12/.pfx) 中找到私钥 + 证书的组合,许多工具以这种格式导入/导出; it's also a keystore format natively supported by the Sun JVM (type PKCS12 ).它也是 Sun JVM(类型PKCS12 )本机支持的密钥库格式。

To make this work, you need to configure what makes the connection with the appropriate keystore.要使其工作,您需要配置与适当的密钥库建立连接的原因。 SSL/TLS client-certificate authentication is always initiated by the server: the client responds with a certificate if it has one (and wants to use it). SSL/TLS 客户端证书身份验证始终由服务器启动:如果客户端有证书(并希望使用它),则客户端会使用证书进行响应。 To configure it for a specific URL, you need to find out what makes the connection (perhaps HttpsURLConnection ) and set it there (unless it's set up in the default context -- even if it's set up in the default context, it will only be used for servers that request it).要为特定 URL 配置它,您需要找出建立连接的原因(可能是HttpsURLConnection )并将其设置在那里(除非它是在默认上下文中设置的——即使它是在默认上下文中设置的,它也只会是用于请求它的服务器)。

To set up the keystore globally on the JVM (which may be what your restrictions prevent you to do), you can set the javax.net.ssl.keyStore javax.net.ssl.keyStorePassword (and related) system properties.要在 JVM 上全局设置密钥库(这可能是您的限制阻止您这样做),您可以设置javax.net.ssl.keyStore javax.net.ssl.keyStorePassword (和相关)系统属性。 (Because the password could be visible, it's better not to do it on the command line). (因为密码可能是可见的,所以最好不要在命令行上进行)。

These system properties are used for the configuration of the default SSLContext (which is used, often transparently, by libraries or classes such as HttpsURLConnection to build the SSLSocketFactory and then SSLSocket , initialized with those properties).这些系统属性用于默认SSLContext的配置(通常透明地由库或类使用,例如HttpsURLConnection来构建SSLSocketFactory ,然后使用这些属性初始化SSLSocket )。

You could build SSLContext from your file specifically for use for that connection.您可以从您的文件中构建SSLContext ,专门用于该连接。 The SSLContext is effectively a factory for the SSLSocketFactory or SSLEngine , and you can set the SSLSocketFactory in a given HttpsURLConnection . SSLContext实际上是SSLSocketFactorySSLEngine的工厂,您可以在给定的HttpsURLConnection设置SSLSocketFactory

The following would build an SSLContext using "/path/to/file.p12" as your keystore (that is the one with your private key and the certificate you're going to send) and keep the default settings for the truststore (you'd need to catch the exception for the input stream too).以下将使用“/path/to/file.p12”作为您的密钥库(即带有您的私钥和您要发送的证书的密钥库)构建一个SSLContext并保留信任库的默认设置(您d 也需要捕获输入流的异常)。

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);

From there you can configure the connection like this (if this is what you're using):从那里您可以像这样配置连接(如果这是您使用的):

HttpURLConnection connection = (HttpURLConnection) url.openConnection();
if (connection instanceof HttpsURLConnection) {
    ((HttpsURLConnection)connection)
         .setSSLSocketFactory(sc.getSocketFactory());
}

Some libraries will let you pass an SSLContext directly (Apache HTTP Client 4 supports that, and this can be done with Apache HTTP Client 3 using this .)一些库会让你直接传递SSLContext (Apache HTTP Client 4 支持这一点,这可以通过 Apache HTTP Client 3 使用 this来完成。)

Note that you don't need to provide the password as a direct parameter when loading the keystore, you could also use a callback (maybe better from the GUI point of view).请注意,您不需要在加载密钥库时提供密码作为直接参数,您也可以使用回调(从 GUI 的角度来看可能更好)。

Perhaps this library could help (but it's not necessary): you could use the KeystoreLoader for its helpers to do this.也许这个库可以提供帮助(但不是必需的):您可以使用KeystoreLoader作为其助手来执行此操作。 There are also SSLContextFactories in this libraries (but you would probably not need any of the wrappers as they tend to be for customizing the trust management or key selection).该库中还有SSLContextFactories (但您可能不需要任何包装器,因为它们往往用于自定义信任管理或密钥选择)。

This is generally how using a client-certificate is configured, but it's difficult to provide more details without clarifications regarding what your restrictions exactly are (and which libraries you're using).这通常是使用客户端证书的配置方式,但是如果不说明您的限制究竟是什么(以及您正在使用哪些库),则很难提供更多详细信息。

You can change the default JSSE keystore through a property when you invoke your app, -Djavax.net.ssl.keystore=somefile .您可以在调用应用程序时通过属性更改默认的 JSSE 密钥库-Djavax.net.ssl.keystore=somefile

So you could import your cert with the keytool command into a keystore and invoke your app pointing to that, eg因此,您可以使用 keytool 命令将您的证书导入密钥库并调用指向该证书的应用程序,例如

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM