我被委托实现一个自定义/独立的Java Web服务器,可以在同一端口上处理SSL和非SSL消息。
我已经实现了一个NIO服务器,并且非SSL请求工作得很好。但是SSL部分让我感到困难,我真的需要一些指导。
到目前为止,我已经完成了以下工作:
为了区分SSL和非SSL消息,我检查入站请求的第一个字节,以查看它是否为SSL/TLS消息。例如:
在parseTLS()方法中,我会像这样实例化SSLEngine:
握手的第一部分似乎运行良好。客户端发送一个握手消息,服务器用4个记录的消息进行响应:
下一步,客户端会发送一个包含三个部分的消息:
SSLEngine解包客户端请求并解析记录,但wrap方法产生了0字节,并带有OK/NEED_UNWRAP的握手状态。换句话说,我没有任何东西可以发送回客户端,握手就会突然停止。
这就是我卡住的地方。
在调试器中,我可以看到SSLEngine,特别是ServerHandshaker,在客户端找不到任何对等证书。当我查看来自客户端的证书记录时,这显而易见,它的长度为0字节。但为什么?
我只能假设HelloServer响应存在问题,但我似乎无法找到原因。服务器似乎正在发送有效的证书,但客户端没有返回任何内容。我的密钥库有问题吗?还是信任库有问题?或者与我实例化SSLEngine的方式有关?我被难住了。
还有几点要注意:
上面代码片段中引用的密钥库和信任库是使用以下教程创建的: http://www.techbrainwave.com/?p=953 我正在使用Firefox 10和IE 9作为客户端来测试服务器。两个Web客户端的结果相同。
我正在使用Sun/Oracle JDK 6和随附其的Java Secure Socket Extension(JSSE)。
期待您可能提供的任何指导,但请不要告诉我我疯了或者使用Netty或Grizzly或其他现有解决方案。目前这不是一个选项。我只想知道我做错了什么。
谢谢您的帮助!
我已经实现了一个NIO服务器,并且非SSL请求工作得很好。但是SSL部分让我感到困难,我真的需要一些指导。
到目前为止,我已经完成了以下工作:
为了区分SSL和非SSL消息,我检查入站请求的第一个字节,以查看它是否为SSL/TLS消息。例如:
byte a = read(buf);
if (totalBytesRead==1 && (a>19 && a<25)){
parseTLS(buf);
}
在parseTLS()方法中,我会像这样实例化SSLEngine:
java.security.KeyStore ks = java.security.KeyStore.getInstance("JKS");
java.security.KeyStore ts = java.security.KeyStore.getInstance("JKS");
ks.load(new java.io.FileInputStream(keyStoreFile), passphrase);
ts.load(new java.io.FileInputStream(trustStoreFile), passphrase);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, passphrase);
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
tmf.init(ts);
SSLContext sslc = SSLContext.getInstance("TLS");
sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLEngine serverEngine = sslc.createSSLEngine();
serverEngine.setUseClientMode(false);
serverEngine.setEnableSessionCreation(true);
serverEngine.setWantClientAuth(true);
一旦SSLEngine被实例化,我使用unwrap/wrap方法处理传入数据,直接使用官方JSSE示例中的代码:
log("----");
serverResult = serverEngine.unwrap(inNetData, inAppData);
log("server unwrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
log("----");
serverResult = serverEngine.wrap(outAppData, outNetData);
log("server wrap: ", serverResult);
runDelegatedTasks(serverResult, serverEngine);
握手的第一部分似乎运行良好。客户端发送一个握手消息,服务器用4个记录的消息进行响应:
handshake (22)
- server_hello (2)
- certificate (11)
- server_key_exchange (12)
- certificate_request (13)
- server_hello_done (14)
下一步,客户端会发送一个包含三个部分的消息:
handshake (22)
- certificate (11)
- client_key_exchange (16)
change_cipher_spec (20)
- client_hello (1)
handshake (22)
*** Encrypted Message ****
SSLEngine解包客户端请求并解析记录,但wrap方法产生了0字节,并带有OK/NEED_UNWRAP的握手状态。换句话说,我没有任何东西可以发送回客户端,握手就会突然停止。
这就是我卡住的地方。
在调试器中,我可以看到SSLEngine,特别是ServerHandshaker,在客户端找不到任何对等证书。当我查看来自客户端的证书记录时,这显而易见,它的长度为0字节。但为什么?
我只能假设HelloServer响应存在问题,但我似乎无法找到原因。服务器似乎正在发送有效的证书,但客户端没有返回任何内容。我的密钥库有问题吗?还是信任库有问题?或者与我实例化SSLEngine的方式有关?我被难住了。
还有几点要注意:
上面代码片段中引用的密钥库和信任库是使用以下教程创建的: http://www.techbrainwave.com/?p=953 我正在使用Firefox 10和IE 9作为客户端来测试服务器。两个Web客户端的结果相同。
我正在使用Sun/Oracle JDK 6和随附其的Java Secure Socket Extension(JSSE)。
期待您可能提供的任何指导,但请不要告诉我我疯了或者使用Netty或Grizzly或其他现有解决方案。目前这不是一个选项。我只想知道我做错了什么。
谢谢您的帮助!