2017-11-18 107 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