Glassfish、Java电子邮件和证书

Glassfish、Java电子邮件和证书,java,ssl,glassfish,jakarta-mail,antivirus,Java,Ssl,Glassfish,Jakarta Mail,Antivirus,我找了很久也找不到答案 我正在使用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

我找了很久也找不到答案

我正在使用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);
}
我还尝试对邮件服务器运行InstallCert,但我得到:

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
并检查注销输出,我可以看到,即使我“无处不在”加载了证书,或者如果我将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]

    ...
找到受信任的证书:
[
[
版本:V3
主题:CN=avast!Web/Mail-Shield Root,O=avast!Web/Mail-Shield,OU=avast!antivirus为SSL/TLS扫描生成
签名算法:SHA1withRSA,OID=1.2.840.113549.1.1.5
密钥:Sun RSA公钥,2048位

模数:--8好的,多基!我已经弄明白了。以下是我5天的旅程今天是如何结束的,简言之

首先,我转储了Java密钥库中的所有证书,因为它正在使用该密钥库:

keytool -list -v -keystore c:\Progra~1\Java\jre7\lib\security\cacerts > allJavaCerts.txt
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
然后我转储了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密钥库列表中,有一个别名为avastslscannerroot的证书,但不在Glassfish密钥库列表中-谢谢

因此,我从Java密钥库导出了avastsslscannerroot证书,并将其导入Glassfish密钥库:

keytool -list -v -keystore c:\Progra~1\Java\jre7\lib\security\cacerts > allJavaCerts.txt
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="*"

属性,当我们从web服务器连接到邮件服务器时,它对我们起作用…

您的本地病毒防护似乎很有效

您的问题是由其所谓的主动保护屏蔽造成的,该屏蔽拦截SSL通信并扫描其恶意内容。为了实现此目的,Avast必须拦截Java程序与SMTPS服务器之间的通信。有关详细信息,请参阅security.stackexchange.com

问题:

由于GlassFish(当然)不信任Avast证书,并且在安装Avast时未将其添加到GlassFish,因此无法建立SSL连接

可能的解决方案:

  • 将Avast证书添加到GlassFish的有效证书列表中(提问者就是这么做的)
  • 禁用Avast的此功能(设置->活动保护->电子邮件保护)
  • 您是否成功访问了“使用别名'localhost-1'将证书添加到密钥库'jssecacerts'中”部分?