SSL通信,它有多难?

时间:2009-03-04 14:49:06

标签: java ssl certificate private main

我的PC上运行了一个Java主应用程序,它可以将XML数据发送到servlet并收回XML数据。 http://iamt.wisconsin.gov/IAM-WiEntUser/WiEntUserService?xml=

我可以使用IE和Firefox中的https://iamt.wisconsin.gov/IAM-WiEntUser/WiEntUserService?xml=因为我允许我加载私有证书。

我想使用Java主应用程序中的https,因为有些数据很敏感。我得到一个MSG =未知证书的IOException。好的,这是有道理的,Java不知道私有证书。

我希望这就像告诉Java信任FireFox证书一样简单。 System.setProperty( “javax.net.ssl.trustStore中”,           “C:/ Documents and Settings / kendajm / Application Data / Mozilla / Firefox / Profiles / 6f8ggdi7.default / cert8.db”); 但是这会产生一个带有MSG =无效密钥库格式的IOException。

SSL通信,它有多难?我花了八个小时试图找出如何做到这一点。这似乎很容易,没有记录或非常困难,没有人有一个很好的例子。

帮助。

4 个答案:

答案 0 :(得分:4)

默认情况下,Mozilla cert8.db密钥库格式不可读(尽管可以“插入”可以解析它的提供程序。)最简单的方法是将证书导入到默认支持的密钥库中。 / p>

首先,您需要一份证书副本。

在Firefox中,访问相关页面。单击窗口右下角状态栏上的“锁定”图标。在出现的对话框中,单击“查看证书”按钮。将出现一个新对话框;选择其“详细信息”选项卡。单击窗口底部的“导出”按钮将证书保存到文件中(使用DER或PEM格式)。

现在,您需要将证书转换为Java使用的密钥库格式。

使用JDK的keytool实用程序:

keytool -import -keystore mykeystore.jks -alias iamt -file iamt.wisconsin.gov

当提示输入密码时,请选择一个新密码,该密码可用于稍后验证密钥库中的证书是否未被篡改。接下来,keytool将提示您是否信任新证书 - 输入yes!您应该有一个名为“mykeystore.jks”的新Java密钥库文件(或您选择的任何内容)。

现在,运行您的程序,将新的密钥库文件指定为“javax.net.ssl.trustStore”属性的值。


顺便说一句,我注意到您从服务中返回Java Bean XMLEncoder输出。这种“长期持久性”格式是JDK的一个被忽视的宝石,但解析不受信任的内容是不安全的。使用此语法,可以在执行解析的JVM中调用任何方法。它有点像带有不受信任的JSON的“eval”。因此,如果我实现了一个客户端服务,我可能不愿意在没有大量额外工作的情况下解析服务的结果,将解析为“沙箱”作为不受信任的代码。而且我假设服务在请求中解析相同的格式,这对服务器来说同样危险。


当您询问有关错误消息的问题时,最好发布整个消息,包括堆栈跟踪(除非它实际上是java.lang.StackOverflowError!)。这对你来说可能毫无意义,但通常它具有在瞬间发现问题所需的信息。

答案 1 :(得分:1)

据我了解,问题是Java不接受自签名证书。如果我错了,请纠正我!

您是否尝试过使用Commons-HttpClient?这有更多选项,在this page上有一个接受自签名证书的指南。另请参阅this sample code

编辑:有关如何将证书导入Java here的指南 - 显然,您需要在运行Java应用程序的每台计算机上执行此操作。 HttpClient选项可能更灵活,具体取决于您的需求。

答案 2 :(得分:1)

一旦我使用keytool使用Java正确注册了证书,我就能够使用自签名证书。

请参阅本指南:http://java.sun.com/j2se/1.4.2/docs/tooldocs/windows/keytool.html

基本上,你: 1.创建自签名证书 2.将其导出到文件 3.将其导入默认密钥库

但是,您尝试整合的政府网站可能会拒绝这样的自签名证书。

答案 3 :(得分:0)

  1. 将证书从IE导出为Base-64编码的X.509(.CER)
  2. 在导出的证书上运行keytool。提供trustStore文件和密码。对信任问题回复“是”。 keytool -import -v -trustcacerts -alias IamtCert -file C:\ Work \ IAM \ Acceptance \ IamAcceptanceCertificate.cer -keystore N:\ WEB \ DEG \ CaCert.dat
  3. 添加两行代码。     System.setProperty( “javax.net.ssl.trustStore中”, “N:\ WEB \ DEG \ CaCert.dat”);     System.setProperty( “javax.net.ssl.trustStorePassword中”, “XXXXXX”);
  4. 一旦你知道该怎么做就不难。其余代码保持不变。 (Servlet有另一种方法来验证不涉及证书的调用者。)

        urlAddress += encodedXmlData;
        URL  url = null;
        HttpURLConnection connection = null;
        StringBuffer result = new StringBuffer();
        try {
            url = new URL( urlAddress );
            connection = (HttpURLConnection)url.openConnection();
        }
        catch( IOException ioe ) {
            System.out.println(classMethod+": IOException: URL Msg="+ioe.getMessage() );
            return(null);
        }           
        connection.setDoInput(true);    // Default value.
        connection.setDoOutput(true);   // Not the default value.
        connection.setUseCaches(false); // Not the default value.
        try {
            connection.setRequestMethod("POST");  // Large pay load.
        }
        catch( ProtocolException pe ){
            System.out.println(classMethod+": ProtocolException: URL Msg="+pe.getMessage() );
            return(null);
        }
        // If true, this URL is being examined in a context in which it makes
        // sense to allow user interactions such as popping up an 
        // authentication dialog.
        connection.setAllowUserInteraction(false);
        try {
            connection.connect();
            BufferedReader bufferedReader = new BufferedReader( new
                    InputStreamReader( connection.getInputStream() ) );
    
            // Retrieve the response
            String inputLine = null;
            while ( (inputLine = bufferedReader.readLine() ) != null ) {
                if ( inputLine.indexOf("</void>") > -1 ) inputLine+='\n';
                result.append(inputLine);
            }
            bufferedReader.close();
            connection.disconnect();
        }
        catch( IOException ioe) {
            System.out.println(classMethod+": IOException: Read Msg="+ioe.getMessage() );
            return(null);
        }