英文:
SSLContext for java web application
问题
在我的桌面Java应用程序中,有一个类通过HTTPS连接使用客户端证书与其他系统进行连接。此连接的一部分是SSLContext,它接收KeyManager[]和TrustManager[],以便实现用户证书和信任存储以与远程服务器进行握手。该类使用Windows存储库获取机器上可用证书的列表,以便用户可以选择合适的证书进行连接。问题是,我正在将此应用程序迁移到云Web服务器(Tomcat),获取证书的过程有很大不同。在Tomcat中,我能够将用户转发到一个HTTPS页面,该页面请求由CA颁发的有效证书。一旦用户访问此页面,浏览器会弹出一个窗口,显示机器上可用的证书列表,以便用户可以选择一个进行身份验证。我的问题是,我应该怎样才能从浏览器身份验证中仅创建一次此SSLContext?我只能获取用户选择的x509证书,但没有私钥。我的问题是,我是否漏掉了某些步骤来获取证书的私钥?我知道Windows存储库不共享私钥,但是当从桌面应用程序调用此过程时,至少提供了密钥的“摘要或标头”(RSAPrivateKey[大小=2048位,类型=交换,容器={########}),这仍然有效。但是通过浏览器,我无法获取此信息。或者是否有另一种方法可以仅使用x509证书创建KeyManager[],而无需提供私钥?
以下是创建与服务器的连接的代码片段:
// 创建连接
SocketFactoryDinamico socketFactory = new SocketFactoryDinamico(X509certificate, PrivateKey);
socketFactory.setFileCacerts(getClass().getResourceAsStream("cacerts"));
KeyManager[] keyManagers = socketFactory.createKeyManagers();
TrustManager[] trustManagers = socketFactory.createTrustManagers();
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(keyManagers, trustManagers, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());
String url = "https://someserver.com";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
以下是从.jsp中获取x509证书的代码片段:
X509Certificate[] certs = (X509Certificate[])
request.getAttribute("javax.servlet.request.X509Certificate");
if (null != certs && certs.length > 0) {
X509Certificate cert = certs[0];
}
以下是配置服务器以请求证书身份验证的代码片段:
<Connector
clientAuth="true"
port="8443"
protocol="HTTP/1.1"
SSLEnabled="true"
scheme="https"
secure="true"
keystoreFile="C:/JavaWeb/tomcat"
keystoreType="JKS" keystorePass="pswd"
truststoreFile="C:/JavaWeb/myTrustStore"
truststoreType="JKS" truststorePass="changeit"
SSLVerifyClient="require" SSLVerifyDepth="10" sslProtocol="TLS"
/>
我尝试从客户端使用JavaScript进行此连接,但是我收到以下错误:
Access to XMLHttpRequest at 'https://remoteserver.com' from origin 'http://localhost' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
以下是我的代码:
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", "https://remoteserver.com");
httpRequest.setRequestHeader("Role-Type", "role");
httpRequest.onreadystatechange = function () {
if (this.readyState === 4) {
if (httpRequest.status === 200) {
console.log('Status:', this.status);
console.log('Headers:', this.getAllResponseHeaders());
console.log('Body:', this.responseText);
console.log(httpRequest);
} else {
console.log("Error");
console.log(httpRequest);
}
}
};
httpRequest.send();
英文:
In my desktop java application there is a class that connects with other system through HTTPS connection using a client certificate. Part of this connection is the SSLContext which receives the KeyManager[] and the TrustManager[] in order to implement the user certificate and the trsut store to get the handshack with the remote server. This class uses the Windows repository to get the list of certificates available on the machine so the user can pick the right one to connect. The problem is that I'm migrating this application to a cloud web server (tomcat) and the procedute to get the certificate is quite different. With tomcat I'm able to forward the user to a https page that requests a valid certificate issued by a CA. Once the user access this page, the browser pops up a window with the certificates available on the machine, so the user can pick one authenticate. My problem now is to create this SSLContext once, from the browser authentication, I can get only the x509 cert selected by the user, but without the Private Key. My question is. Am I missing something to get the certificate Private Key? I know that windows repository does not share the private key, but when this procedure is called from a desktop application, at least the "resume or header" (RSAPrivateKey[size = 2048 bits, type = Exchange, container = {########}) of the key is provided, which still works. But through the browser, I cannot get this information. Or is there another way to create the KeyManager[] with just the x509 certificate without provide the private key?
here is a piece of the code which creates the connection with the server..
// create the connection
SocketFactoryDinamico socketFactory = new SocketFactoryDinamico(X509certificate, PrivateKey);
socketFactory.setFileCacerts(getClass().getResourceAsStream("cacerts"));
KeyManager[] keyManagers = socketFactory.createKeyManagers();
TrustManager[] trustManagers = socketFactory.createTrustManagers();
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(keyManagers, trustManagers, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslc.getSocketFactory());
String url = "https://someserver.com";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
and here is the code which gets the x509 certificate on the .jsp...
X509Certificate[] certs = (X509Certificate[])
request.getAttribute("javax.servlet.request.X509Certificate");
if (null != certs && certs.length > 0) {
X509Certificate cert = certs[0];
}
and here is the server configuration to request the certificate authentication
<Connector
clientAuth="true"
port="8443"
protocol="HTTP/1.1"
SSLEnabled="true"
scheme="https"
secure="true"
keystoreFile="C:/JavaWeb/tomcat"
keystoreType="JKS" keystorePass="pswd"
truststoreFile="C:/JavaWeb/myTrustStore"
truststoreType="JKS" truststorePass="changeit"
SSLVerifyCLient="require" SSLVerifyDepth="10" sslProtocol="TLS"
/>
I´ve tried to make this connection from the client side with javascript, however I get this error:
Access to XMLHttpRequest at 'https://remoteserver.com' from origin 'http://localhost' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Here is my code:
var httpRequest = new XMLHttpRequest();
httpRequest.open("POST", "https://remoteserver.com");
httpRequest.setRequestHeader("Role-Type", "role");
httpRequest.onreadystatechange = function () {
if (this.readyState === 4) {
if (httpRequest.status === 200) {
console.log('Status:', this.status);
console.log('Headers:', this.getAllResponseHeaders());
console.log('Body:', this.responseText);
console.log(httpRequest);
} else {
console.log("Erro");
console.log(httpRequest);
}
}
};
httpRequest.send();
专注分享java语言的经验与见解,让所有开发者获益!
评论