2014-01-28 40 views
0

我试图安装服务器端客户端aith在我的Java应用程序如下:无法设置客户端X509身份验证在Java中

SslContextFactory sslContextFactory = new SslContextFactory(); 
sslContextFactory.setNeedClientAuth(true); 

TrustManager[] trustManagers = new TrustManager[ 
     ]{new X509TrustManager() { 
    @Override 
    public void checkClientTrusted(X509Certificate[] arg0, String arg1) 
      throws CertificateException { 
     LoggerFactory.getLogger().fatal("Check client trusted"); 
    } 

    @Override 
    public void checkServerTrusted(X509Certificate[] arg0, String arg1) 
      throws CertificateException { 
     LoggerFactory.getLogger().fatal("Check server trusted"); 
    } 

    @Override 
    public X509Certificate[] getAcceptedIssuers() { 
     LoggerFactory.getLogger().fatal("Returning accepted issuers"); 

     try { 
      InputStream inStream = new FileInputStream("/home/sk_/client.cer"); 
      CertificateFactory cf = CertificateFactory.getInstance("X.509"); 
      X509Certificate cert = (X509Certificate) cf.generateCertificate(inStream); 
      inStream.close(); 

      return new X509Certificate[]{cert}; 
     } catch (Exception e) { 
      e.printStackTrace(); 
      LoggerFactory.getLogger().fatal("AFDASDFSAASD", e); 

      return null; 
     } 
    } 
}}; 

SSLContext context = SSLContext.getInstance("TLSv1.1"); 
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); 
FileInputStream fin = new FileInputStream(".hive/certs/mjolnirr.jks"); 
KeyStore ks = KeyStore.getInstance("JKS"); 
ks.load(fin, "passwd".toCharArray()); 

kmf.init(ks, "passwd".toCharArray()); 
context.init(kmf.getKeyManagers(), trustManagers, null); 

SSLEngine engine = context.createSSLEngine(); 
engine.setNeedClientAuth(true); 
engine.setEnabledCipherSuites(engine.getSupportedCipherSuites()); 
engine.setEnabledProtocols(engine.getSupportedProtocols()); 

sslContextFactory.setSslContext(context); 

而且我已经添加SSL设置客户端:

-Djavax.net.debug=ssl 
-Djavax.net.ssl.keyStoreType=jks 
-Djavax.net.ssl.keyStore=/home/sk_/client-truststore.jks 
-Djavax.net.ssl.keyStorePassword=passwd 
-Djavax.net.ssl.trustStoreType=jks 
-Djavax.net.ssl.trustStore=/home/sk_/client-truststore.jks 
-Djavax.net.ssl.trustStorePassword=passwd 

client.cer从客户端信任库(client-trustore.jks)中导出。客户失败,出现以下错误:

javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake 
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:946) 
at sun.security.ssl.SSLSocketImpl.waitForClose(SSLSocketImpl.java:1705) 
at sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:122) 
at sun.security.ssl.Handshaker.sendChangeCipherSpec(Handshaker.java:972) 
at sun.security.ssl.ClientHandshaker.sendChangeCipherAndFinish(ClientHandshaker.java:1087) 
... 

我的应用程序有什么问题?

编辑我添加调试的sslhandshake到服务器,这里是输出:

*** ServerHelloDone 
qtp935608254-28, WRITE: TLSv1 Handshake, length = 1442 
qtp935608254-29, READ: TLSv1 Handshake, length = 77 
*** Certificate chain 
*** 
qtp935608254-29, fatal error: 42: null cert chain 
javax.net.ssl.SSLHandshakeException: null cert chain 
%% Invalidated: [Session-1, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA] 
qtp935608254-29, SEND TLSv1 ALERT: fatal, description = bad_certificate 
qtp935608254-29, WRITE: TLSv1 Alert, length = 2 
qtp935608254-29, fatal: engine already closed. Rethrowing javax.net.ssl.SSLHandshakeException: null cert chain 
+0

请使用-Djavax.net.debug = ssl运行服务器,握手并在此处发布相关输出。 – EJP

+0

@EJP请参阅编辑 – skayred

回答

1

您的客户端证书不是由服务器的信任的信任。服务器发送一个受信任CA的列表,客户端必须发送其中一个受信任的证书。它不能,所以它发送一个空证书链。如果您的客户端证书是自签名的或由不受信任的CA签名的,则需要将其从您的客户端密钥库导出并作为可信证书导入到服务器的信任库中。