如何通过Web服务实现“简单SSL”?

时间:2011-07-25 00:12:35

标签: java web-services ssl

我知道如何使用证书保护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连接一样)

5 个答案:

答案 0 :(得分:5)

Java运行时环境在cacerts文件中附带了许多(使用最广泛的)证书颁发机构。如果您用于保护服务的证书由其中一个根CA签名,则您无需担心与客户端共享任何证书。

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

的详细信息

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

答案 1 :(得分:2)

如果我理解正确,那么您希望仅使用服务器端身份验证,就像连接到浏览器中的https站点一样,而无需客户端管理任何证书。

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

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

答案 2 :(得分: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/

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

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