Java HTTPS 服务器:双向 SSL 认证

3

我开发了一个基于Java 7的HTTPS服务器(使用com.sun.net.httpserver.HttpsServer),用于SOAP Web服务(主要受到这个SO答案的影响),不同之处在于该服务器需要客户端认证。这是我使用的服务器配置代码:

final InetSocketAddress address = new InetSocketAddress( localhost, 8888 );
this.httpsServer = HttpsServer.create( address, 0 );

// ... KeyStore configuration ...

// configure the HTTPS server
this.httpsServer.setHttpsConfigurator( new HttpsConfigurator( sslContext )
{
   @Override
   public void configure(final HttpsParameters params)
   {
      try
      {
         // initialize the SSL context
         final SSLContext c = SSLContext.getDefault();
         final SSLEngine engine = c.createSSLEngine();
         params.setNeedClientAuth( true );
         params.setCipherSuites( engine.getEnabledCipherSuites() );
         params.setProtocols( engine.getEnabledProtocols() );

         // get the default parameters
         final SSLParameters defaultSSLParameters = c.getDefaultSSLParameters();
         params.setSSLParameters( defaultSSLParameters );
      }
      catch ( final Exception e )
      {
         LOG.error( ExceptionUtils.getStackTrace( e ) );
      }
   }
} );

然而,当客户端连接时,我发现客户端验证没有得到强制执行!我目前正在使用自签名证书在本地主机上进行测试,但似乎任何客户端都能够连接。我尝试了 SoapUI(据我所知,我没有配置它发送任何证书)以及在客户端模式下使用和不使用证书的 openssl。

openssl s_client -cert client.pem -connect localhost:8888 -debug
openssl s_client -connect localhost:8888 -debug

我已经使用Java选项-Djavax.net.debug=all启动了服务器,但没有看到任何相关部分表明客户端身份验证或要求客户端呈现其证书的请求。我确实看到客户端验证了服务器的证书!

我想拒绝任何未提供有效证书的客户端。我该如何做?


我没有看到你使用密钥库初始化SSLContext sslContext.init(myKeyManagerFactory.getKeyManagers(), myTrustManagerFactory.getTrustManagers(), null); 在这里查看代码示例:https://dev59.com/Opbfa4cB1Zd3GeqPs2St - Mike
是的,这段代码被省略了,因为它与这个问题无关。 - Markus L
1个回答

5

经过长时间的搜索,我注意到HttpsConfiguratorconfigure(..)方法是错误的。我没有正确设置SSLParameters

它应该像这样:

@Override
public void configure(final HttpsParameters params)
{
   try
   {
      final SSLParameters sslParams = getSSLContext().getDefaultSSLParameters();
      final SSLEngine sslEngine = getSSLContext().createSSLEngine();
      sslParams.setNeedClientAuth( true );
      sslParams.setCipherSuites( sslEngine.getEnabledCipherSuites() );
      sslParams.setProtocols( sslEngine.getEnabledProtocols() );
      params.setSSLParameters( sslParams );
   }
   catch ( final Exception e )
   {
      LOG.error( ExceptionUtils.getStackTrace( e ) );
   }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接