终于解决了问题。看来VMware采取了非常不同的路径。问题被误解了。
首先,我使用WireShark跟踪连接,在任何时候服务器都没有要求(需要或想要)证书。然而,VirtualCenter(VC)提供了一种注册证书作为连接的一部分,然后使用该证书进行身份验证的方法。为了使其工作,他们提供了一种隧道连接的方式。
我使用的顺序是:
首先指定要连接的URL为https://:(注意协议是安全的,但端口不是)。
初始套接字将打开到明文端口。但是,由于协议是https,将强制调用我的自己的SSLSocketFactory。在我的套接字工厂中,我会收到对我的public Socket createSocket(Socket s, String host, int port, boolean autoClose)
方法的调用,这允许我按照自己的喜好将我的套接字转换为SSLSocket。
我的代码基本上是这样的:
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
throws IOException {
s.setKeepAlive(true);
String connectReq = "CONNECT /sdkTunnel HTTP/1.1\r\n\r\n";
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
writer.write(connectReq, 0, connectReq.length());
writer.flush();
READ_AND_VERIFY_INITIAL_RESPONSE();
SSLSocket sock = (SSLSocket) origSslSockFactory
.createSocket(s, s.getInetAddress().getHostName(), s.getPort(), true);
return sock;
}
在上面的代码块中,origSslSockFactory是被你的实现替换掉的SSLSocketFactory。在我的情况下,它是sun.security.ssl.SSLSocketFactoryImpl的一个实例。
在这个过程之后,调用ExtensionManager.setExtensionCertificate()成功。随后,所有对SessionManager.loginExtensionByCertificate()的调用也都成功了。
我想发布这篇文章,因为似乎有很多关于这个问题的疑问。
-Djavax.net.debug=ssl
或至少-Djavax.net.debug=ssl:handshake
来调试握手过程,以查看是否收到了CertificateRequest
并检查其中包含的certificate_authorities
列表。 - Bruno