如何从JavaFX应用程序连接到HTTPS URL

Asp*_*ant 3 java ssl https f5 javafx-2

我有一个Javafx应用程序,通过HTTPS将GET和POST请求发送到安全的Web服务.托管web服务的服务器上的SSL设置是单向ssl,即Javafx应用程序验证服务器的标识,但服务器不验证胖客户端的标识.

应用程序服务器位于具有证书的F5后面(由外部机构签名).

对于浏览器而言,这不会成为问题,因为浏览器本身会处理验证服务器的身份并向用户显示相关警告.但对于胖客户端,我不确定如何在发送请求之前验证服务器的身份.请告诉我如何在Javafx应用程序中处理此问题.

我确实在这里这里问了一个与之相关的问题,但那些没有帮助.所以,请原谅我对这个主题的有限知识.

任何帮助,将不胜感激.

use*_*873 5

如果您的证书在Firefox/java中不起作用,则很可能它的发行者不为Firefox/java所知.

如何使它工作:

  1. 获取服务器的完整证书链.你可以用Firefox做到这一点.查看证书 - >详细信息 - >导出到.pem文件.在您的案例链中,将包含至少2个证书(cerver证书和CA证书,CA可能是自签名的或可能不是).在.pem文件中导出CA证书.

  2. 现在您可以强制java信任该CA,它可以通过各种方式完成,例如,您可以在jre cacerts中添加CA证书或为HttpsURLConnection创建自定义SSLContext.

  3. 如果您执行DNS或etchosts修改,请回滚它.连接地址应与证书CN匹配,包括通配符.

  4. 使用该代码连接到您的服务器:

    public void test() throws Exception {
        URL u = new URL(
                "https://my-server.com/my-webservices/data");
        HttpsURLConnection http = (HttpsURLConnection) u.openConnection();
        http.setSSLSocketFactory(createSSLContext().getSocketFactory());
        http.setAllowUserInteraction(true);
        http.setRequestMethod("GET");
        http.connect();
    
        InputStream is = http.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder stringBuilder = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null)
        {
            stringBuilder.append(line
                    + "\n");
        }
        System.out.println(stringBuilder.toString());
    
    }
    
    private SSLContext createSSLContext() throws Exception {
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        FileInputStream in = new FileInputStream("path_to_ca_file.pem");
        KeyStore trustStore = KeyStore.getInstance("JKS");
        trustStore.load(null);
        try {
            X509Certificate cacert = (X509Certificate) cf.generateCertificate(in);
            trustStore.setCertificateEntry("ca", cacert);
        } finally {
            IOUtils.closeQuietly(in);
        }
    
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(trustStore);
    
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, tmf.getTrustManagers(), new SecureRandom());
        return sslContext;
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 是的,应用程序可以使用它从服务器获得的任何证书,但它只消除了一种攻击 - 嗅探.MITM http://en.wikipedia.org/wiki/Man-in-the-middle_attack和etc/hosts重写仍然可以应用于那种https. (2认同)
  • 这取决于您为服务器设置的证书.通常,这可以通过设置全信任SSL上下文来实现.您已经知道如何执行此操作,[例如](http://www.nakov.com/blog/2009/07/16/disable-certificate-validation-in-java-ssl-connections/)但是从中获取证书众所周知的权威(VeriSign,GeoTrust等)更好.作为劣势,它会定期花费你一些钱.作为优势,您不必费心更新CA(java维护实际的CA列表) (2认同)