我必须能够在后端系统中指定用于验证配置文件(不是系统密钥库,但用户配置)中的HTTPS连接的证书和密钥,并尝试了以下方法:
openssl pkcs12
命令导出信息并转换为base64格式,以便能够从硬连线的String
实例中读取它InputStream
的{{1}}中读取该信息,并输入Base64.Decode
方法。 (正确读取信息,KeyStore#load()
实例实际存储用户信息,已经检查过)KeyStore
(来自KeyStore
库)中指定SSLContext.Builder
作为关键信息的来源(这是我认为未正确完成的)org.apache.http.conn.ssl
来访问客户端身份验证服务器,该服务器根据客户端提供的证书对客户端进行身份验证。用于测试连接的代码如下所示:
HTTPS
在与服务器协商/**
* $Id: $
*
* Copyright (C) 2017 BaseN.
*
* All rights reserved.
*/
package net.basen.testing;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Base64;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
/**
* Tester for https connections.
*/
public class CheckSSLAccess {
/**
* Main program
* @param args
* @throws KeyStoreException
* @throws IOException
* @throws CertificateException
* @throws NoSuchAlgorithmException
* @throws UnrecoverableKeyException
*/
public static void main( String[] args ) {
String ksContents = /* Keystore contents altered intentionally, but correctly reflect a private key and certificate */
"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";
try {
InputStream is = Base64.getMimeDecoder().wrap( new ByteArrayInputStream( ksContents.getBytes() ) );
KeyStore kst = KeyStore.getInstance( "pkcs12" );
kst.load( is, null );
KeyManagerFactory.getInstance( KeyManagerFactory.getDefaultAlgorithm() )
.init( kst, null );
SSLContext.setDefault( SSLContexts.custom()
.loadTrustMaterial(kst)
.loadKeyMaterial( kst, null )
.build() );
} catch( Exception e ) {
e.printStackTrace();
return;
}
try {
CloseableHttpClient cl = HttpClients.createDefault();
/* server address has been also altered to protect access privacy */
HttpGet get = new HttpGet( "https://www.server.com/autheticated_url" );
CloseableHttpResponse resp = cl.execute( get );
System.out.println(resp.getStatusLine());
Header[] headers = resp.getAllHeaders();
for (int i = 0; i < headers.length; i++)
System.out.println(headers[i]);
System.out.println();
InputStream in = resp.getEntity().getContent();
byte[] buffer = new byte[1024];
int n;
while ((n = in.read(buffer)) > 0) {
System.out.write( buffer, 0, n );
}
if (n < 0) {
System.err.println( "n == " + n );
}
} catch( Exception e ) {
e.printStackTrace();
return;
}
}
} /* CheckSSLAccess */
凭据时,库会发出以下异常,就像没有使用用户证书一样。我不确切知道此代码中缺少的内容,以便客户端选择正确的证书并与服务器正确协商。
很抱歉,但由于项目问题,示例中显示的证书已更改为新生成的证书,以及要访问的服务器的URL。
SSL
问题是
在javax.net.ssl.SSLProtocolException: handshake alert: unrecognized_name
at sun.security.ssl.ClientHandshaker.handshakeAlert(ClientHandshaker.java:1438)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:2016)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1125)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:290)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:259)
at org.apache.http.impl.conn.HttpClientConnectionOperator.connect(HttpClientConnectionOperator.java:125)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:319)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:363)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:219)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:195)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:86)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
at net.basen.testing.CheckSSLAccess.main(CheckSSLAccess.java:109)
初始化中,为了选择(或将SSLContext
与实际HTTPS呼叫相关联)HTTPS呼叫中的SSLContext
凭据,它应该缺少什么?
在question和调试模式中激活选项后,在ssl握手中从不考虑用户证书,所以我担心这个问题与被引用的问题无关。出于某种原因,hanshake在服务器证书交换上停止,客户端证书永远不会被交换:
KeyStore