0

我目前正在处理的 JSF 应用程序有一个奇怪的问题。似乎我的程序有两个部分发生冲突。

有两个部分:

  • “银行”功能
  • 邮件功能

银行功能的相关部分(仅用于本练习的假银行):

String path = FacesContext.getCurrentInstance().getExternalContext()                .getRealPath("/") + "/WEB-INF/sec/certs.jks";

ErrorHandler.trace(path);

System.setProperty("javax.net.ssl.trustStore", path);

在这里,它使用银行服务器的证书设置信任库。

邮件部分如下所示:

Properties props = new Properties();
props.put("mail.smtp.auth", this.smtpServer.isAuthenticated());
props.put("mail.smtp.starttls.enable", this.smtpServer.isTls());
props.put("mail.smtp.host", this.smtpServer.getHostaddr());
props.put("mail.smtp.port", this.smtpServer.getPort());
props.put("mail.smtps.auth", "true");
props.put("mail.smtp.debug", "true");

final String username = this.smtpServer.getUsername();
final String password = this.smtpServer.getPassword();

Session session = Session.getDefaultInstance(props,
        new javax.mail.Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });

session.setDebug(true);

重现问题的一种方法:

我面临的问题是,如果我启动应用程序,例如,使用“更改邮件”功能,我会立即收到通知邮件。那里没问题。然后我会尝试购买一种产品,从而触发银行功能。

这就是问题出现的地方:

Communication Error: javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException
 - with linked exception:
[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]

重现问题的另一种方法:

现在假设我重新启动我的应用程序并尝试订购一些东西,这一次它会工作,但邮件功能被此错误消息破坏:

DEBUG: setDebug: JavaMail version 1.4.7
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 465, isSSL true
TRACE Error Could not connect to SMTP host: smtp.gmail.com, port: 465

底线:

如果我触发银行然后邮件 -> 邮件不工作 如果我触发邮件然后银行 -> 银行不工作

任何人都可以在那里找到问题?

谢谢!

4

2 回答 2

1

Your "banking functionality" is changing the trust store. That new trust store needs to have the certificates necessary to validate the SSL connection with your mail server. You can initialize your trust store with all the CA certificates from the JDK default trust store, or you can add just the specific certificate for your mail server - see the InstallCert program. Finally, you can configure JavaMail to use a separate trust store, or change your banking functionality to use a trust store explicitly rather than overriding the default trust store; those are probably more complicated.

于 2014-01-12T08:35:43.813 回答
0

问题是,如果没有设置 trustStore,邮件功能就可以工作(因为它使用的是系统的默认 trustStore,它位于:

/Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home/jre/lib/security/cacerts

在 Mac 上。

银行功能正在使用它自己的证书,该证书位于:

MyProject/.../WEB-INF/sec/certs.jks

每次 JavaMail 尝试向 Google 的 SMTP 服务器进行身份验证时,它都会尝试使用 certs.jks trustStore,即使我取消了在邮件方法中设置的银行功能的 trustStore 属性。

使固定:

在邮件方法的开头:

String path = FacesContext.getCurrentInstance().getExternalContext()
            .getRealPath("/")
            + "WEB-INF/sec/certs.jks";
System.setProperty("javax.net.ssl.trustStore", path);

将默认的cacertskeyStore 导入到我们自己的自定义 keyStore 中:

keytool -importkeystore -srckeystore certs.jks -destkeystore cacerts
于 2014-01-13T09:20:54.217 回答