我在理解TLS/SSL如何处理电子邮件时遇到了一些问题。
我有些问题要问。
我得到的错误消息是:“握手时远程主机关闭连接”。
当我将相同的代码部署到我们的暂存环境并发送电子邮件时,代码第一次运行良好。开发服务器和暂存服务器都在同一个网络中,并且都没有运行反病毒程序。
我唯一能想到的是,为什么它在开发环境中第一次不能工作,是因为我正在使用调试器执行代码,而且由于这个原因,代码会慢一些。
你知道我为什么会收到这个错误吗?
2a)还是我仍然需要以某种方式指定证书?
或者该代码是否从服务器获取证书,并使用证书加密数据并将加密数据来回发送到电子邮件服务器?
我知道它应该像这里描述的那样工作: RFC 3207定义SMTP连接如何使用加密。一旦建立了连接,客户机就会发出STARTTLS命令。如果服务器接受这一点,客户端和服务器将协商一种加密机制。如果协商成功,随后在它们之间传递的数据将被加密。
下面的代码是这样做的吗?
socket.setKeepAlive(true);
SSLSocket sslSocket = (SSLSocket) ((SSLSocketFactory) SSLSocketFactory.getDefault()).createSocket(
socket,
socket.getInetAddress().getHostAddress(),
socket.getPort(),
true);
sslSocket.setUseClientMode(true);
sslSocket.setEnableSessionCreation(true);
sslSocket.setEnabledProtocols(new String[]{"SSLv3", "TLSv1"});
sslSocket.setKeepAlive(true);
// Force handshake. This can throw!
sslSocket.startHandshake();
socket = sslSocket;
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));发布于 2016-07-07 01:59:19
如果您只是在基础套接字关闭后再次执行startHandshake(),那么它就不应该工作。如果您回到进行TCP连接(例如new Socket(host,port))以及初始SMTP交换和STARTTLS,那么是的,我希望它能够避免任何影响之前连接的问题。
是的,在调试过程中由于延迟而导致服务器超时是非常可能的,但是要确定您需要检查服务器上的日志。
间接的,是的。SSLSocketFactory创建一个链接到SSLContext的SSLSocket,其中包括通常从信任存储文件加载的TrustManager。您的代码默认为默认的SSLContext,默认信任库加载了一个TrustManager,如果存在,它就是文件jssecacerts,而在运行的JRE中,则是lib/security目录中的cacerts。如果您的JRE没有被修改(由您或您系统上其他授权的任何人修改),则根据您的变体或Java的打包,安装的JRE通常没有jssecacerts,包含或链接到一个cacerts文件,该文件(最初)包含大约100个“知名”的根证书,或者像赛门铁克、GoDaddy、Comodo等已建立的证书颁发机构。
2a)还是我仍然需要以某种方式指定证书?
因为握手是成功的,显然不是。
或者该代码是否从服务器获取证书,并使用证书加密数据并将加密数据来回发送到电子邮件服务器?
有点/有点/不完全。除了不适用于此的一些例外情况外,在SSL/TLS握手中,服务器总是提供自己的证书,通常是将其证书链接到受信任的根证书(例如上述Symantec等)的中间证书或“链”证书。服务器证书通常用于对服务器进行身份验证,有时是单独的,但通常与其他机制(特别是Diffie-Hellman临时DHE或其椭圆曲线变体ECDHE)相结合,用于建立一组对称的密钥值,然后用于对两个方向的数据进行加密和身份验证。有关更完整的解释,请参见规范问题和(多部分!)security.SX https://security.stackexchange.com/questions/20803/how-does-ssl-work/中的答案
下面的代码是这样做的吗?
它正在现有套接字上启动SSLv3或TLSv1客户端会话。我不知道你还有什么问题。
你最好省去setEnabledProtocols()。Sun/Oracle Java版本8是目前唯一支持的版本,默认情况下它支持TLS 1.0、1.1和1.2。1.1,特别是1.2肯定比1.0更好,因此如果服务器支持它们,就应该使用它们。(Sun/Oracle 7更有问题;它实现了1.1和1.2,但默认情况下不启用客户端。在这里,我将查看.getSupportedProtocols,如果支持1.1和1.2,但没有启用,我将添加enable它们。但如果可能的话,我只需升级到8。其他版本的Java,特别是IBM,在密码细节上有很大的不同。)
除非绝对必要,否则不应该提供SSLv3;它现在被贵宾狗严重破坏了(在security.SX上搜索几十个关于贵宾犬的Qs )。我会尝试不使用它,并且只有在服务器坚持暂时重新启用它的情况下,尽可能使用TLS1.0到1.2的_along,并同时敦促服务器升级,以便我可以再次删除它。
https://stackoverflow.com/questions/38235123
复制相似问题