【发布时间】:2016-02-24 15:55:29
【问题描述】:
我想在 SSL/TLS 握手期间使用我的 Java 应用程序检索已发送的 Microsoft SQL Server (2012/2014) 的公共服务器证书。
我的环境优先:
- MS SQL 设置为使用强制加密
- 只接受 SSL/TLS 连接
- 拥有自签名 CA 和由该 CA 颁发的证书
- 颁发的证书被 MS SQL 服务器使用
为了以编程方式实现这一点,我正在使用我自己的信任管理器实现。请在此处查看相关代码的摘录:
SSLSocket sslSocket = (SSLSocket) getFactory().createSocket(socket, host, port, true);
sslSocket.startHandshake();
getFactory():
private SSLSocketFactory getFactory() throws IOException
{
// irrelevant code removed here
return factory();
}
工厂():
private static SSLSocketFactory factory() throws NoSuchAlgorithmException, KeyManagementException
{
SSLSocketFactory factorySingleton;
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(null, getTrustManager(), null);
factorySingleton = ctx.getSocketFactory();
return factorySingleton;
}
getTrustManager():
private static TrustManager[] getTrustManager()
{
X509Certificate[] server = null;
X509Certificate[] client = null;
X509TrustManager tm = new X509TrustManager()
{
X509Certificate[] server1 = null;
X509Certificate[] client1 = null;
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[0];
}
public void checkServerTrusted(X509Certificate[] chain, String x)
{
server1 = chain;
Logger.println("X509 Certificate chain: " + chain);
}
public void checkClientTrusted(X509Certificate[] chain, String x)
{
client1 = chain;
Logger.println("X509 Certificate chain: " + chain);
}
};
return new X509TrustManager[]{tm};
}
我期待对startHandshake() 的调用会在某个时候使我的应用程序从我的SQL 服务器接收不同的证书,并尝试调用我的自定义信任管理器来验证它们。此时我将拥有证书(X509Certificate[] 链)。但是我的信任管理器没有被调用,或者至少两个检查器方法中的断点都没有被调用。
这是我用作参考的 MS 文档之一:https://msdn.microsoft.com/en-us/library/bb879919(v=sql.110).aspx#Anchor_1
“在 SSL 握手期间,服务器将其公钥证书发送给客户端。”
【问题讨论】:
-
这应该完全符合您的预期。也许 ssl-handshake 或 tcp-connection 已经失败了?
-
我不这么认为,因为我可以看到使用 jvm 调试选项发生的握手,如果我手动导出服务器证书并将其放在我的机器上的信任存储中并将该证书用于 ssl连接就可以了。
-
您的日志记录可能有问题?我测试了代码(使用 System.out.println),调试输出按预期显示
-
嘿,你看过 Intallcert.java 类了吗? github.com/escline/InstallCert这个类连接到服务器,从客户端获取服务器证书,并将其添加到信任库中......也许你可以稍微修改一下来实现你所需要的
标签: java sql-server ssl