【问题标题】:How to make 'simple SSL' thru Web Services?如何通过 Web 服务制作“简单 SSL”?
【发布时间】:2011-10-12 05:50:41
【问题描述】:

我知道如何使用证书保护 Web 服务。这是我的客户代码:

  SSLContext ssl = SSLContext.getInstance("SSLv3");
  KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
  String password = Configuration.getConfig("keyStorePassword");
  store.load(new FileInputStream(new File(Configuration.getConfig("keyStore"))), password.toCharArray());
  kmf.init(store, password.toCharArray());
  KeyManager[] keyManagers = new KeyManager[1];
  keyManagers = kmf.getKeyManagers();
  TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  tmf.init(store);
  TrustManager[] trustManagers = tmf.getTrustManagers();
  ssl.init(keyManagers, trustManagers, new SecureRandom());

  HttpsConfigurator configurator = new HttpsConfigurator(ssl);
  Integer port = Integer.parseInt(Configuration.getConfig("port"));
  HttpsServer httpsServer = HttpsServer.create(new InetSocketAddress(Configuration.getConfig("host"), port), 0);
  httpsServer.setHttpsConfigurator(configurator);

  Implementor implementor = new Implementor(); // class with @WebService etc.
  HttpContext context = (HttpContext) httpsServer.createContext("/EventWebService");
  Endpoint endpoint = Endpoint.create( implementor );
  endpoint.publish(context);

现在,如何制作“简单 SSL”?如何在客户端不存储证书的情况下进行 SSL 连接。 (就像在浏览器中通过 HTTPS 连接一样)

【问题讨论】:

    标签: java web-services ssl


    【解决方案1】:

    您可以通过这种方式控制 https 服务器是否需要客户端证书:

    HttpsConfigurator cfg = new HttpsConfigurator(sslCtx){
      public void configure(HttpsParameters params) {
            SSLParameters sslparams = getSSLContext().getDefaultSSLParameters();
    
            // Modify the default params:
            // Using this, server will require client certs
            //sslparams.setNeedClientAuth(true);
    
            // Using this, server will request client certs. But if not available,
            // it will continue anyway.
            sslparams.setWantClientAuth(true);
    
            params.setSSLParameters(sslparams);
      }
    };
    HttpsServer httpsS = HttpsServer.create(new InetSocketAddress(8081), 50);
    httpsS.setHttpsConfigurator(cfg);
    

    如果不需要客户端证书,客户端可以在没有客户端证书的情况下连接,所以简单的调用 https 就可以了。

    在我的博客中,您可以看到有关如何绕过服务器证书和主机名验证的客户端示例(虽然不推荐,但很有用,例如用于测试) http://jakubneubauer.wordpress.com/2011/09/06/java-webservice-over-ssl/

    【讨论】:

      【解决方案2】:

      浏览器中的 HTTPS 可以正常工作,因为客户端上有一个包含 SSL 证书的信任库。换句话说:有证书存储在客户端。

      如果您想要在客户端不存储任何证书的 HTTPS,我认为您应该看看 this article,它解释了如何关闭 HTTPS 连接上的默认证书验证。

      【讨论】:

        【解决方案3】:

        Java 运行时环境在 cacerts 文件中确实带有很多(使用最广泛的)证书颁发机构。如果您用来保护您的服务的证书是由这些根 CA 之一签名的,那么您不必担心与客户端共享任何证书。

        但是,如果您使用自签名证书,并且不想在信任库中传递/导入证书,那么您可以实现自定义 X509TrustManager 并为您的连接创建自定义 SSLContext。更多详情请看blog

        自签名证书对于开发和测试环境很有用,但您确实应该考虑让您的服务器证书从 Verisign、Thwate 等公认的证书颁发机构签名。

        【讨论】:

        • 我认为 TrustAlmostEverythingManager 就是我想要的。我正在使用精确的 IP 连接到服务器(因此不可能有人欺骗)。我只是想保护连接不被窃听。我想对了吗?也许在未来,将需要生成客户端和服务器证书。
        • 啊...是的,但是如果您的 Web 服务消费者在您的组织之外,那么他们就很难信任自签名证书。我建议先花几块钱让你的客户感觉更好。我还建议获取一个正确的域,而不是共享一个带有 IP 地址的 WSDL。自签名证书非常适合 Intranet 应用程序和测试环境,但对于外部客户来说,多花几块钱就会有很长的路要走!
        • 客户在组织之外,为什么信任很难?你的意思是很难验证服务器?我知道来自 CA 的证书会更好,这个环境的管理员也知道这一点。现在,它只是不依赖于我。也许,将来会有适当的证书(由 CA 颁发)等。
        • 是的——我不是说技术上会更难。只是人们很难信任提供自签名证书的站点,尤其是在 Web 服务数据交换包含敏感信息的情况下。但我感觉你已经意识到了后果,所以不用担心:-)
        【解决方案4】:

        如果我对您的理解正确,那么您只想进行服务器端身份验证,就像您在浏览器中连接到 https 站点一样,不需要您的客户端管理任何证书。

        您的客户端将照常连接,只需将连接 URL 中的 http 替换为 https。 Java 以cacerts 的形式管理自己的一组“默认受信任的根CA 权限”,这是一个位于$JRE HOME/lib/security 中的JKS 密钥库文件。如果您从任何 CA 购买证书,该证书的颁发证书源于 cacerts 中包含的证书之一,则客户端的证书验证将自动成功。谷歌“SSL/TLS 服务器证书”,你会找到合适的供应商。

        另一方面,如果您将使用自颁发的证书,那么除了将您的自制证书导入客户端的证书信任库中之外,没有其他方法可以使客户端上的证书验证成功。但这就是为什么“真正的” SSL/TLS 证书需要花钱而您自己颁发的证书不需要花钱的原因——任何人都可以生成自己的本地证书,但信任它们是完全不同的故事。

        【讨论】:

          【解决方案5】:

          只需使用 HTTPS 建立连接。只要客户端使用标准的受信任证书,它就可以正常工作。如果他们有自签名证书,您需要将证书导入 java 密钥库。

          【讨论】:

          • 我想制作安全的 WebServices,但我不想在客户端机器上放置任何证书。我想像浏览器一样通过 HTTPS 连接到服务器。客户端和服务器都是我写的,我可以改。
          • 我的意思是:简单的 TLS 握手 en.wikipedia.org/wiki/Transport_Layer_Security
          • 浏览器预装了公共可信证书,Java 密钥库也是如此。他们不会动态协商……否则他们不会被信任。
          猜你喜欢
          • 2013-01-08
          • 2016-11-09
          • 1970-01-01
          • 2015-04-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-04
          • 1970-01-01
          相关资源
          最近更新 更多