来自Java客户端的SSL错误,但在Firefox中使用POSTER

时间:2014-08-28 16:37:08

标签: java ssl

我只是在我的服务器上设置SSL证书。我很确定他们的设置正确。在浏览器中转到https://mydomain.com/myapp时,页面会正确加载,绿色锁定会显示在地址栏中。

从Firefox执行POST> POSTER到此HTTPS网址我收到有效回复。

如果我从Java客户端执行相同的POST,则会收到以下错误:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

在我的服务器上,我已将CA_ROOT证书放在JAVA ... / jre / lib / security / cacert密钥库中。

这是我的Java客户端发布的代码。

URL url = new URL(Global.SERVER_URL);
HttpsURLConnection connection = null;
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setReadTimeout(45000);
connection.setRequestProperty("Content-Type", "text/json");
connection.connect();

请注意:这不是自签名的CERT。它由CA发布

我有一种感觉,Glassfish没有发送完整的证书链。我查看了浏览器获得的证书,它是完整的证书链。我查看了SSL错误,这只是中间证书,而且是我的域名。

如何让Glassfish发送完整的Cert链?

检查SSL链

openssl.exe s_client -connect mydomain.com:443

返回

WARNING: can't open config file: /usr/local/ssl/openssl.cnf
Loading 'screen' into random state - done
CONNECTED(00000190)
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = US, ST = <edited>, L = <edited>, O = <edited>, OU = <edited>, CN = <edited>
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
 0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
   i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
Server certificate
-----BEGIN CERTIFICATE-----
<edited>
-----END CERTIFICATE-----
subject=/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
issuer=/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---
No client certificate CA names sent
---
SSL handshake has read 1676 bytes and written 513 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
    Protocol  : TLSv1.2
    Cipher    : ECDHE-RSA-AES128-GCM-SHA256
    Session-ID: <edited>

    Session-ID-ctx:
    Master-Key: <edited>
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    Start Time: 1410274974
    Timeout   : 300 (sec)
    Verify return code: 21 (unable to verify the first certificate)
---
read:errno=0

布鲁诺对概念的接受答案

其他详情:

  1. 获取Keystore Explorer。它是浏览密钥库的理想GUI工具。
  2. 使用Keystore Explorer打开keystore.jks。
  3. 右键单击有问题的证书(mydomain)和查看详细信息&gt;证书链详细信息
  4. 如果没有显示完整的Cert链,则通过右键单击证书编辑证书链&gt;附加证书来添加它。
  5. 重启Glassfish。

5 个答案:

答案 0 :(得分:4)

浏览器和Java使用不同的受信任根证书集,默认情况下,浏览器从操作系统获取此信息,Java支持自己的列表,这就是为什么它在浏览器中可能是绿色的并且在Java中不支持< / p>

要检查哪些证书支持您的Java版本: <jre_path>\bin\keytool -keystore "<jre_path>\lib\security\cacerts" -storepass changeit -list

如果您没有看到您的证书,只需将其添加到<jre_path>\lib\security\cacerts文件中。

答案 1 :(得分:2)

---
Certificate chain
 0 s:/C=US/ST=<edited>/L=<edited>/O=<edited>/OU=<edited>/CN=<edited>
   i:/O=Cybertrust Inc/CN=Cybertrust Public SureServer SV CA
---

与您在评论中所说的不同,根据此输出,您的服务器不会发送任何中间证书。证书链只有一个证书(位置0):服务器证书。

  

在我的服务器上,我已将CA_ROOT证书放在JAVA ... / jre / lib / security / cacert密钥库中。

在服务器端的信任库中添加中间证书对服务器提供的链没有影响(它仅用于验证客户端,如果适用)。

您需要确保使用完整链设置密钥库条目,如this question中所述,遵循与this answer相同的步骤。

您在浏览器中看到的内容很可能是它重建的链,浏览器也可能知道这些中间CA证书,而JRE可能不会(使用不同的信任锚集):您只需要通过正确显示完整链,增加默认JRE接受服务器证书的机会。 (请注意,您不需要在链中提供根CA证书本身,它不会造成损害,但它只是网络开销。)

答案 2 :(得分:0)

SSLHandshakeException:

  当失败的连接看起来像这样时,会出现

。通常表明存在某种类型的证书验证问题,很可能您的Truststore不包含它需要的受信任的根证书。并且   表示客户端和服务器无法协商所需的安全级别。连接不再可用。

     

javax.net.ssl.SSLHandshakeException:   sun.security.validator.ValidatorException:PKIX路径构建   失败:sun.security.provider.certpath.SunCertPathBuilderException:   无法找到所请求目标的有效证书路径

使用以下代码发送HTTP POST请求的详细示例。

private void sendPost() throws Exception {

        String url = "https://selfsolve.apple.com/wcResults.do";
        URL obj = new URL(url);
        HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();

        //add reuqest header
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", "Mozilla/5.0");
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        con.setRequestProperty("Content-Type", "text/json");

        String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";

        // Send post request
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        wr.writeBytes(urlParameters);
        wr.flush();
        wr.close();

        int responseCode = con.getResponseCode();
        System.out.println("\nSending 'POST' request to URL : " + url);
        System.out.println("Post parameters : " + urlParameters);
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        //print result
        System.out.println(response.toString());

    }

如果响应代码为200,则表示看起来不错 有关更多详细信息,请参阅以下链接。

答案 3 :(得分:0)

Java密钥库 cacerts ,但不是 cacert

答案 4 :(得分:0)

我认为你正在讨论我在这里回答的同一个问题:

https://stackoverflow.com/a/25734956/1083338