Glassfish,Java 电子邮件和证书
Glassfish, Java email and certificate
我找了很久都找不到答案。
我正在使用 Glassfish 并想通过我们的 smtp 服务器发送电子邮件。
我已经获得了服务器的证书:
openssl s_client -connect mail.example.com:587 -starttls smtp > our.cer
我已经清理了 cer 文件以仅包含证书数据。
我到处导入它:
keytool -import -alias mail.example.com -file our.cer -keystore c:\Progra~1\Java\jre7\lib\security\cacerts
keytool -import -alias mail.example.com -file our.cer -keystore c:\Progra~1\Java\JDK17~1.0_4\jre\lib\security\cacerts
keytool -import -alias mail.example.com -file our.cer -keystore c:\PROGRA~1\GLASSF~1.0\GLASSF~1\domains\domain1\config\cacerts.jks
但我收到以下错误:
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by...
...
Caused by...
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我的代码片段:
...
Properties properties = System.getProperties();
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", "mail.example.com");
properties.put("mail.smtp.user", "example@example.com");
properties.put("mail.smtp.password", "some.password");
properties.put("mail.smtp.port", "587"));
properties.put("mail.smtp.auth", "true"));
properties.put("mail.smtp.from", "example@example.com"));
properties.put("mail.transport", "smtp"));
...
Authenticator mailAuthenticator = new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(properties.getProperty("mail.smtp.user"),
properties.getProperty("mail.smtp.password"));
}
};
try
{
// Get the default Session object.
Session session = Session.getDefaultInstance(properties, mailAuthenticator);
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setSubject("Hallo world!");
mimeMessage.setFrom(new InternetAddress(properties.getProperty("mail.smtp.from")));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("example@example.com"));
mimeMessage.setText("Some text message...");
Transport transport = session.getTransport(properties.getProperty("mail.transport"));//"smtp"
int port = Integer.parseInt(properties.getProperty("mail.smtp.port"));//587
transport.connect(properties.getProperty("mail.smtp.host"),//"mail.example.com"
port,
properties.getProperty("mail.smtp.user"),//"example@example.com"
properties.getProperty("mail.smtp.password"));//Clear text password
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
LOG.info("...done sending email");
}
catch (AddressException e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
catch (MessagingException e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
catch (Exception e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
我也尝试过 Mkyong's suggestion to run InstallCert (source) 针对邮件服务器,但我得到:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
更新 1
我已将证书加载到以下其他位置:
keytool -import -alias mail.example.com -file our.cer -keystore c:\PROGRA~1\GLASSF~1.0\GLASSF~1\domains\domain1\config\keystore.jks
keytool -import -alias mail.example.com -file our.cer -keystore c:\GLASSFISH\config\keystore.jks
keytool -import -alias mail.example.com -file our.cer -keystore c:\GLASSFISH\config\cacerts.jks
我还设置了这些属性:
System.setProperty("javax.net.ssl.keyStore", "c:\GLASSFISH\config\keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.ssl.trustStore", "c:\GLASSFISH\config\cacerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
我还打开了 ssl 调试(Glassfish 控制台、服务器、属性)javax.net.debug=ssl
。
它可以在独立测试应用程序 (Java SE) 中运行,但不能在 Glassfish 中运行。
更新 2
使用 javax.net.debug=ssl
并检查日志输出我可以看到,即使我已经加载了证书 "everywhere" 或者如果我将 Glassfish 指向 java 密钥库, Glassfish 缺少此证书。独立测试应用程序有它:
adding as trusted cert:
Subject: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Algorithm: RSA; Serial number: 0x14128fa09c50b64ba6d5c99875872673
Valid from Wed Feb 04 08:56:17 CAT 2015 until Sat Feb 01 08:56:17 CAT 2025
(注意序列号...)
好像是Glassfish缺少的证书;因为独立测试应用程序找到了它:
Found trusted certificate:
[
[
Version: V3
Subject: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
modulus: ---8<---
public exponent: 65537
Validity: [From: Wed Feb 04 08:56:17 CAT 2015, : Sat Feb 01 08:56:17 CAT 2025]
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
SerialNumber: [ 14128fa0 9c50b64b a6d5c998 75872673]
...
(看序列号...)
请帮忙
好啦好啦!我想通了。简而言之,今天我的 5 天旅程就这样结束了……
首先,我从 Java 密钥库中转储了所有证书,因为它正在使用该密钥库:
keytool -list -v -keystore c:\Progra~1\Java\jre7\lib\security\cacerts > allJavaCerts.txt
然后我转储了 Glassfish 密钥库中的所有证书,以查看证书是否已正确导入:
keytool -list -v -keystore c:\WORKSP~1\GLASS\config\cacerts.jks > allGFCerts.txt
在 Java 密钥库列表中,我注意到邮件服务器的证书是由 Avast 颁发的...很奇怪,对吧?
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
并且在 Java 密钥库列表中有 Alias name: avastsslscannerroot
的证书,但不在 Glassfish 密钥库列表中 - 谢谢 Beyond Compare v3
所以我从 Java 密钥库导出 avastsslscannerroot 证书并将其导入 Glassfish 密钥库:
keytool -export -keystore c:\Progra~1\Java\jre7\lib\security\cacerts -alias avastsslscannerroot -file avastsslscannerroot.cer
keytool -import -alias avastsslscannerroot -file avastsslscannerroot.cer -keystore c:\WORKSP~1\GLASS\config\keystore.jks
keytool -import -alias avastsslscannerroot -file avastsslscannerroot.cer -keystore c:\WORKSP~1\GLASS\config\cacerts.jks
现在可以使用了...
然后它没有在服务器上...经过一些搜索我发现了这个:
mail.smtp.ssl.trust="*"
属性 它对我们有用,因为我们正在从 our 网络服务器连接到 our 邮件服务器...
您的本地病毒防护似乎是 Avast。
您的问题是由所谓的 Active Protection Shield 引起的,它会拦截 SSL 流量并扫描其中的恶意内容。为了实现这一点,Avast 必须拦截您的 Java-Program 和 SMTPS-Server 之间的通信。有关详细信息,请参阅 this question or this question 的 security.stackexchange.com
问题:
因为 Avast 证书(当然)不受 GlassFish 信任并且在安装 Avast 时没有添加到 Glassfish,所以无法建立 SSL 连接
可能的解决方案:
- 将 Avast-Certificate 添加到 GlassFishs 有效证书列表(这就是提问者所做的)
- 禁用 Avast 的此功能(设置 -> 主动保护 -> 电子邮件保护)
我找了很久都找不到答案。
我正在使用 Glassfish 并想通过我们的 smtp 服务器发送电子邮件。
我已经获得了服务器的证书:
openssl s_client -connect mail.example.com:587 -starttls smtp > our.cer
我已经清理了 cer 文件以仅包含证书数据。
我到处导入它:
keytool -import -alias mail.example.com -file our.cer -keystore c:\Progra~1\Java\jre7\lib\security\cacerts
keytool -import -alias mail.example.com -file our.cer -keystore c:\Progra~1\Java\JDK17~1.0_4\jre\lib\security\cacerts
keytool -import -alias mail.example.com -file our.cer -keystore c:\PROGRA~1\GLASSF~1.0\GLASSF~1\domains\domain1\config\cacerts.jks
但我收到以下错误:
javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
...
Caused by...
...
Caused by...
...
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
我的代码片段:
...
Properties properties = System.getProperties();
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", "mail.example.com");
properties.put("mail.smtp.user", "example@example.com");
properties.put("mail.smtp.password", "some.password");
properties.put("mail.smtp.port", "587"));
properties.put("mail.smtp.auth", "true"));
properties.put("mail.smtp.from", "example@example.com"));
properties.put("mail.transport", "smtp"));
...
Authenticator mailAuthenticator = new Authenticator()
{
@Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(properties.getProperty("mail.smtp.user"),
properties.getProperty("mail.smtp.password"));
}
};
try
{
// Get the default Session object.
Session session = Session.getDefaultInstance(properties, mailAuthenticator);
MimeMessage mimeMessage = new MimeMessage(session);
mimeMessage.setSubject("Hallo world!");
mimeMessage.setFrom(new InternetAddress(properties.getProperty("mail.smtp.from")));
mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress("example@example.com"));
mimeMessage.setText("Some text message...");
Transport transport = session.getTransport(properties.getProperty("mail.transport"));//"smtp"
int port = Integer.parseInt(properties.getProperty("mail.smtp.port"));//587
transport.connect(properties.getProperty("mail.smtp.host"),//"mail.example.com"
port,
properties.getProperty("mail.smtp.user"),//"example@example.com"
properties.getProperty("mail.smtp.password"));//Clear text password
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
LOG.info("...done sending email");
}
catch (AddressException e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
catch (MessagingException e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
catch (Exception e)
{
LOG.log(Level.SEVERE, "Error while sending email", e);
}
我也尝试过 Mkyong's suggestion to run InstallCert (source) 针对邮件服务器,但我得到:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
更新 1
我已将证书加载到以下其他位置:
keytool -import -alias mail.example.com -file our.cer -keystore c:\PROGRA~1\GLASSF~1.0\GLASSF~1\domains\domain1\config\keystore.jks
keytool -import -alias mail.example.com -file our.cer -keystore c:\GLASSFISH\config\keystore.jks
keytool -import -alias mail.example.com -file our.cer -keystore c:\GLASSFISH\config\cacerts.jks
我还设置了这些属性:
System.setProperty("javax.net.ssl.keyStore", "c:\GLASSFISH\config\keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "changeit");
System.setProperty("javax.net.ssl.trustStore", "c:\GLASSFISH\config\cacerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
我还打开了 ssl 调试(Glassfish 控制台、服务器、属性)javax.net.debug=ssl
。
它可以在独立测试应用程序 (Java SE) 中运行,但不能在 Glassfish 中运行。
更新 2
使用 javax.net.debug=ssl
并检查日志输出我可以看到,即使我已经加载了证书 "everywhere" 或者如果我将 Glassfish 指向 java 密钥库, Glassfish 缺少此证书。独立测试应用程序有它:
adding as trusted cert:
Subject: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Algorithm: RSA; Serial number: 0x14128fa09c50b64ba6d5c99875872673
Valid from Wed Feb 04 08:56:17 CAT 2015 until Sat Feb 01 08:56:17 CAT 2025
(注意序列号...)
好像是Glassfish缺少的证书;因为独立测试应用程序找到了它:
Found trusted certificate:
[
[
Version: V3
Subject: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
Key: Sun RSA public key, 2048 bits
modulus: ---8<---
public exponent: 65537
Validity: [From: Wed Feb 04 08:56:17 CAT 2015, : Sat Feb 01 08:56:17 CAT 2025]
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
SerialNumber: [ 14128fa0 9c50b64b a6d5c998 75872673]
...
(看序列号...)
请帮忙
好啦好啦!我想通了。简而言之,今天我的 5 天旅程就这样结束了……
首先,我从 Java 密钥库中转储了所有证书,因为它正在使用该密钥库:
keytool -list -v -keystore c:\Progra~1\Java\jre7\lib\security\cacerts > allJavaCerts.txt
然后我转储了 Glassfish 密钥库中的所有证书,以查看证书是否已正确导入:
keytool -list -v -keystore c:\WORKSP~1\GLASS\config\cacerts.jks > allGFCerts.txt
在 Java 密钥库列表中,我注意到邮件服务器的证书是由 Avast 颁发的...很奇怪,对吧?
Issuer: CN=avast! Web/Mail Shield Root, O=avast! Web/Mail Shield, OU=generated by avast! antivirus for SSL/TLS scanning
并且在 Java 密钥库列表中有 Alias name: avastsslscannerroot
的证书,但不在 Glassfish 密钥库列表中 - 谢谢 Beyond Compare v3
所以我从 Java 密钥库导出 avastsslscannerroot 证书并将其导入 Glassfish 密钥库:
keytool -export -keystore c:\Progra~1\Java\jre7\lib\security\cacerts -alias avastsslscannerroot -file avastsslscannerroot.cer
keytool -import -alias avastsslscannerroot -file avastsslscannerroot.cer -keystore c:\WORKSP~1\GLASS\config\keystore.jks
keytool -import -alias avastsslscannerroot -file avastsslscannerroot.cer -keystore c:\WORKSP~1\GLASS\config\cacerts.jks
现在可以使用了...
然后它没有在服务器上...经过一些搜索我发现了这个:
mail.smtp.ssl.trust="*"
属性 它对我们有用,因为我们正在从 our 网络服务器连接到 our 邮件服务器...
您的本地病毒防护似乎是 Avast。
您的问题是由所谓的 Active Protection Shield 引起的,它会拦截 SSL 流量并扫描其中的恶意内容。为了实现这一点,Avast 必须拦截您的 Java-Program 和 SMTPS-Server 之间的通信。有关详细信息,请参阅 this question or this question 的 security.stackexchange.com
问题:
因为 Avast 证书(当然)不受 GlassFish 信任并且在安装 Avast 时没有添加到 Glassfish,所以无法建立 SSL 连接
可能的解决方案:
- 将 Avast-Certificate 添加到 GlassFishs 有效证书列表(这就是提问者所做的)
- 禁用 Avast 的此功能(设置 -> 主动保护 -> 电子邮件保护)