2017-11-18 187 views
1

我的目标:我正在研究Jetty Embedded的集成,这将使其易于使用。 interface将允许用于集成TLS证书的外部源,而不使用Java KeyStore。没有JKS的嵌入式Jetty上的TLS

这将允许建立分布式Web服务时更大的灵活性(在我的情况下是experimental, self-hosted CDN)。

但是,我在构建集成时遇到了问题。存根实现是in this repository

我试过的东西:我试过更换key managertrust manager,并为其中的每个函数设置断点。但是,当试图访问服务器时,这些断点永远不会被触发。相反,我遇到这个错误:

javax.net.ssl.SSLHandshakeException: no cipher suites in common 
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478) 
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535) 
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813) 
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781) 
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) 
    at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:621) 
    at org.eclipse.jetty.server.HttpConnection.fillRequestBuffer(HttpConnection.java:322) 
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:231) 
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) 
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112) 
    at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:261) 
    at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:150) 
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112) 
    at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672) 
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590) 
    at java.lang.Thread.run(Thread.java:748) 

我试图分析“标准”的码头设置,其中一个证书从密钥库,但没有多少运气。我无法找到Jetty获取我应该覆盖的密码/证书信息的地方。

我的问题:如何让Jetty使用my own certificate source代替Java KeyStore和TrustStore?

+1

这个异常通常意味着服务器找不到私钥和匹配的证书。显然你的'KeyManager'没有正确安装,或者它之前会被调用。 – EJP

+0

谢谢,我将尝试追踪密钥管理器在“股票”版本与我自己的版本中的安装方式。 – Janoszen

回答

0

@EJP我指出了正确的方向,所以这里是如何做到这一点:

下面是它需要如何做。

首先,设置码头为TLS:

HttpConfiguration https = new HttpConfiguration(); 
https.addCustomizer(new SecureRequestCustomizer()); 
SslContextFactory sslContextFactory = new JettySslContextFactory(configuration.getSslProviders()); 
ServerConnector sslConnector = new ServerConnector(
    server, 
    new SslConnectionFactory(sslContextFactory, "http/1.1"), 
    new HttpConnectionFactory(https) 
); 
sslConnector.setPort(httpsPort); 

注意该类JettySslContextFactory。此类扩展内置X509ExtendedKeyManager,需要重写protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception方法,以提供定制的KeyManager,像这样:

@Override 
protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception { 
    return new KeyManager[] { 
     new JettyX509ExtendedKeyManager(certificateProviders) 
    }; 
} 

除此之外,下面的步骤在每个连接运行:

  1. SNI匹配器与SNI主机名进行协商。这似乎是SNI主机名甚至可用的唯一地方。
  2. 查询密钥管理器以获取特定密钥类型(EC或RSA)的别名(密钥ID的种类)。这里我们需要从SNI匹配器中获取主机名,否则我们不知道匹配哪个主机名。
  3. 根据别名(密钥ID),我们可以返回私钥和证书。

至少这是我从调试这个问题中收集到的。完整代码is online here