可用的密码网络应用程序

Available ciphers web application

此 java 应用程序需要使用 SMTP 和 TLS 发送电子邮件。

邮件发送代码在独立 java 应用程序 (java MailClient) 和我们之前的环境中执行时工作正常,但在 Tomcat 8 环境中执行时失败 (Tomcat 8 AWS Beanstalk,OpenJDK 64 位服务器 VM(构建 25.171-b10,混合模式))。

相关邮件发送代码(使用javax 1.6.1):

Properties props = new Properties();
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.host", smtpServerProperties.get(HOST_PROPERTY));
props.put("mail.smtp.port", smtpServerProperties.get(PORT_PROPERTY));
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
Authenticator auth = new Authenticator() {
    protected PasswordAuthentication getPasswordAuthentication() {
        return new PasswordAuthentication(smtpServerProperties.get(TLS_USER_PROPERTY), smtpServerProperties.get(TLS_PASSWORD_PROPERTY));
    }
};
Session session = Session.getInstance(props, auth);
MimeMessage email = createEmail(session, smtpSender, recipients, subject, content);
Transport transport = session.getTransport();
transport.connect(smtpServerProperties.get(HOST_PROPERTY),smtpServerProperties.get(TLS_USER_PROPERTY), smtpServerProperties.get(TLS_PASSWORD_PROPERTY) );
transport.sendMessage(email, email.getAllRecipients());

我得到的错误:

Caused by: java.io.EOFException: SSL peer shut down incorrectly
    at sun.security.ssl.InputRecord.read(InputRecord.java:505)
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:983)
    ... 13 more

而且我怀疑问题是当 运行 "inside" tomcat 时应用程序的可用密码不知何故受到限制,然后它失败了。在 SSL 日志中,我可以看到 'unsupported cipher suite' 的列表在应用程序以及用于握手的初始 TLS 版本之间非常不同:

里面 tomcat:

Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_128_GCM_SHA256
%% No cached client session
*** ClientHello, TLSv1

外面:

Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1
Ignoring unsupported cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 for TLSv1.1
Ignoring unsupported cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 for TLSv1.1
%% No cached client session
*** ClientHello, TLSv1.2

编辑

相同的应用程序 运行 在 Tomcat 中可以成功地与 mongoDb 服务器通信(mongo-java-driver-3.2.2 ) 以及使用 https(标准 HttpURLConnection)的其他 Web 应用程序,并且在这两种情况下,ClientHello 使用 TLSv1.2。

问题是:tomcat 环境 limiting/changing 如何成为 javax.mail 的可用密码,即使它 (真的似乎是) 使用相同的 java 环境?

肯定是密码问题。这肯定是因为您的 SSL 握手失败了,但发生这种情况的原因有很多。

因为在应用程序托管在 Tomcat 之前您没有发现问题,这表明您可能正在处理 SSL 信任库问题。获取由您的 SMTP 服务器的 SSL 端点提供的 SSL 证书,并使用 (java/bin) 密钥工具将该证书导入 Tomcat 的受信任密钥库。如果它已经存在,您将收到一条类似于 "It's already in here, do you want to re-import it?"

的消息

重新导入它不会有什么坏处,但信任库通常不会动态加载,因此在您执行该信任库导入后,您应该重新启动 Tomcat。您可以键入不带参数的 (java/bin) keytool 以获得帮助屏幕,但导入命令看起来像这样:

keytool -import -file smtpcert.cer -keystore -tomcattrust

您的文件名 (.cer) 和信任库名称可能与上面不同,如果提示输入密码,我认为默认密码是 changeit。

祝你好运!

tldr:完整的 Web 应用程序有一个依赖项,包括旧版本的邮件 class (1.4),但它不起作用。修复是在 pom.file:

中添加排除项
<dependency>
    <groupId>org.jboss.resteasy</groupId>
    <artifactId>resteasy-multipart-provider</artifactId>
    <version>2.2.1.GA</version>
    <exclusions>
        <exclusion>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
        </exclusion>
    </exclusions>
</dependency>

原因比预期的要长:

  • 同一个 Web 应用程序在(完全)不同的环境中运行 - windows 服务器、Sun JDK8、Tomcat7
  • 发送电子邮件 class 在一个 "core" 项目中,该项目不包括任何其他邮件依赖项
  • 最初怀疑 class/implementation 在 "inside" 和 "outside" 版本中使用,但它们是 "same"(至少是名字)

用于查找的步骤:

正在使用以下标志执行 java 应用程序:

-verbose:class
-verbose:jni

并检查日志:

  • 独立应用程序(当 运行 我的 "main" class,我使用了来自网络部署的库):[Loaded com.sun.mail.smtp.SMTPTransport from file:/var/lib/tomcat8/webapps/myapp/WEB-INF/lib/javax.mail-1.6.1.jar]
  • 网络应用:[Loaded com.sun.mail.smtp.SMTPTransport from file:/var/lib/tomcat8/webapps/myapp/WEB-INF/lib/mail-1.4.jar]

最终验证基于 运行 一个 mvn 依赖关系 mvn dependency:tree 并看到两个邮件依赖关系:

[INFO] +- com.my.company:my-core:jar:1.70:compile
[INFO] |  \- com.sun.mail:javax.mail:jar:1.6.1:compile
...
[INFO] +- org.jboss.resteasy:resteasy-multipart-provider:jar:2.2.1.GA:compile
[INFO] |  +- javax.mail:mail:jar:1.4:compile