【问题标题】:Trust all SSL certificates in Java Playframework 2.2信任 Java Playframework 2.2 中的所有 SSL 证书
【发布时间】:2013-10-10 06:42:02
【问题描述】:

我正在尝试在 Play Framework 中调用网络服务(具有自签名 SSL 证书) 使用以下函数:

public static play.libs.F.Promise<Result> webcall() {
       String feedUrl = "https://10.0.1.1/client/api";
       final play.libs.F.Promise<Result> resultPromise = WS.url(feedUrl).get().map(
                    new Function<WS.Response, Result>() {
                        public Result apply(WS.Response response) {
                            return ok("Feed title:" + response.asJson().findPath("title").toString());
                        }
                    }
            );
            return resultPromise;
        }

它在日志中抛出以下错误,

[error] play - Cannot invoke the action, eventually got an error: java.net.ConnectException: General SSLEngine problem to https://10.0.1.1/client/api
[error] application - 

! @6fpimpnp6 - Internal server error, for (GET) [/webcall] ->

play.api.Application$$anon$1: Execution exception[[ConnectException: General SSLEngine problem to https://10.0.1.1/client/api]]
    at play.api.Application$class.handleError(Application.scala:293) ~[play_2.10.jar:2.2.0]
    at play.api.DefaultApplication.handleError(Application.scala:399) [play_2.10.jar:2.2.0]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.0]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2$$anonfun$applyOrElse$3.apply(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.0]
    at scala.Option.map(Option.scala:145) [scala-library.jar:na]
    at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$2.applyOrElse(PlayDefaultUpstreamHandler.scala:261) [play_2.10.jar:2.2.0]
java.net.ConnectException: General SSLEngine problem to https://10.0.1.1/client/api
    at com.ning.http.client.providers.netty.NettyConnectListener.operationComplete(NettyConnectListener.java:103) ~[async-http-client.jar:na]
    at org.jboss.netty.channel.DefaultChannelFuture.notifyListener(DefaultChannelFuture.java:427) ~[netty.jar:na]
    at org.jboss.netty.channel.DefaultChannelFuture.notifyListeners(DefaultChannelFuture.java:413) ~[netty.jar:na]
    at org.jboss.netty.channel.DefaultChannelFuture.setFailure(DefaultChannelFuture.java:380) ~[netty.jar:na]
    at org.jboss.netty.handler.ssl.SslHandler.setHandshakeFailure(SslHandler.java:1417) ~[netty.jar:na]
    at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1293) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1362) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:513) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:790) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:758) ~[na:1.7.0_40]
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624) ~[na:1.7.0_40]
    at org.jboss.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1225) ~[netty.jar:na]
Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:192) ~[na:1.7.0_40]
    at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1683) ~[na:1.7.0_40]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:278) ~[na:1.7.0_40]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270) ~[na:1.7.0_40]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341) ~[na:1.7.0_40]
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153) ~[na:1.7.0_40]
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:385) ~[na:1.7.0_40]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.7.0_40]
    at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:283) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:138) ~[na:1.7.0_40]
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196) ~[na:1.7.0_40]
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268) ~[na:1.7.0_40]
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380) ~[na:1.7.0_40]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292) ~[na:1.7.0_40]
    at sun.security.validator.Validator.validate(Validator.java:260) ~[na:1.7.0_40]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326) ~[na:1.7.0_40]

如果我使用 HttpsURLConnection 调用该服务,则添加

TrustManager[] trustAllcerts = new TrustManager[]{
    new X509TrustManager() {

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }

        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            // TODO Auto-generated method stub

        }
    }};

javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext.getInstance("SSL");
sc.init(null, trustAllcerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {

    @Override
    public boolean verify(String arg0, SSLSession arg1) {
        // TODO Auto-generated method stub
        return false;
    }
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);

如何信任 Play Framework 中的所有 自签名 / 不受信任 ssl 证书?

【问题讨论】:

    标签: java ssl playframework-2.0 ssl-certificate


    【解决方案1】:

    尝试将以下代码添加到conf/application.conf 文件中

    ws.acceptAnyCertificate=true
    

    如果您使用Promise 类,这将起作用。但是如果你是通过其他 HttpClients 调用服务就不行了。

    更新:从 Play Framework 2.5 开始,您应该使用以下内容 -

    play.ws.ssl.loose.acceptAnyCertificate=true
    

    您可以在开发环境中执行此操作,但切勿在生产环境中执行此操作,因为这可能会构成安全威胁。在生产中,将客户端的证书安装在您的密钥库中。

    【讨论】:

    • 请不要这样做。您可以从 Play TLS 激活器示例中生成所需的证书:typesafe.com/activator/template/play-tls-example,然后将 cacerts 添加到 ws.ssl 中的 trustManager(参见下面的示例)
    • 这是危险的,安全的。您不想盲目接受任何证书
    • 从 play 2.5 开始,您可以使用 play.ws.ssl.loose.acceptAnyCertificate=true。但如前所述,这可能非常危险,请在使用前阅读playframework.com/documentation/2.5.x/LooseSSL
    【解决方案2】:

    请不要接受所有证书 - 您可以将信任管理器与自定义证书一起使用,然后回退到默认信任存储。

    ws.ssl {
      trustManager = {
         stores = [
          { path: ${store.directory}/exampletrust.jks }     # Added trust store
          { path: ${java.home}/lib/security/cacerts } # Fallback to default JSSE trust store
         ]
      }
    }
    

    更多详情请见http://www.playframework.com/documentation/2.3.x/ExampleSSLConfig

    【讨论】:

    • 我是 play 框架的新手,想知道 store.directory 到底在哪里?打包如何与自定义信任存储一起使用?我把它放在 conf 中并用路径 'conf/exampletrust.jks' 引用。是否会与应用程序正确打包?
    • 是的,没关系。有关一些自定义证书的示例,请参阅 github.com/wsargent/play-ws-with-letsencrypt/blob/master/conf/…
    • 看起来如果相对路径用于信任存储,它将相对于应用程序的启动位置。是否可以在配置中使用变量来引用已部署应用程序的根目录,以便可以在不使用绝对路径的情况下部署信任库?
    • 您可以使用 HOCON 替换和回退到环境变量来定义绝对路径 github.com/typesafehub/config/blob/master/… 使用 ${?ABSOLUTE_PATH} 等。
    【解决方案3】:

    只需在信任库中安装您尝试信任的证书即可。

    不要盲目接受所有证书。这会使您的应用程序容易受到 MITM 攻击。

    即使只是为了开发,那也是人们在截止日期时忘记删除的那种代码和设置。

    您可能遇到的下一个问题是主机名匹配。您正在使用https://10.0.1.1/ 中的 IP 地址,因此您的证书应该具有该 IP 地址的 SAN 条目,而不仅仅是其 CN 中的该 IP 地址。更多详情here。不要使用您在代码中设置的HostnameVerifier(出于相同的原因)。

    【讨论】:

    • 感谢您的宝贵建议
    【解决方案4】:

    你可以尝试设置这些参数

    -Dmail.smtp.ssl.trust=* -Dmail.smtp.ssl.checkserveridentity=false
    

    在启动您的应用程序时。以下是所有参数的列表:https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html

    【讨论】:

      猜你喜欢
      • 2014-01-07
      • 2012-10-13
      • 1970-01-01
      • 2014-02-14
      • 1970-01-01
      • 1970-01-01
      • 2015-04-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多