如何在SSLContext中使用自定义密钥库来驱动HTTPS连接

时间:2017-02-28 08:12:27

标签: java authentication certificate keystore sslcontext

我必须能够在后端系统中指定用于验证配置文件(不是系统密钥库,但用户配置)中的HTTPS连接的证书和密钥,并尝试了以下方法:

  • 首先将用户证书和私钥编码为在Base64 in config中编码的PKCS#12文件。 (我已从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

0 个答案:

没有答案