简体   繁体   English

我如何停用SSL验证?

[英]How I can deactivate the SSL verification?

I'm trying to make a call to REST API, but I get the following exception (Complete StackTrace at the end): 我正在尝试调用REST API,但是我得到以下异常(最后完成StackTrace):

"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"

I asked the API provider about this problem and says that there is something wrong with the SSL library That you are using. 我向API提供商询问了这个问题,并说你正在使用的SSL库有问题。

How would you solve this problem? 你会如何解决这个问题? With this same code (below) I did make calls to the NIMBLE API REST without problems, but in this case it does not work. 使用相同的代码(下面)我确实调用了NIMBLE API REST而没有任何问题,但在这种情况下它不起作用。 Then, I do not have any file cert (.cer). 然后,我没有任何文件证书(.cer)。

I need deactivate the SSL verification because the security methods is the API KEY that I already have. 我需要停用SSL验证,因为安全方法是我已经拥有的API KEY。

Any suggestions? 有什么建议?

Thank you very much! 非常感谢你!

==== Console: ==== ====控制台:====

POST https://api.nexalogy.com/project/create?api_key=XXXXXXXXXXXXXXXXXXXX
HTTP Header:"Content-Type" "application/json"
HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}]
api_key:XXXXXXXXXXXXXXXXXXXX
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

I have also tried the following form and exception is the same: 我也试过以下表格,例外是一样的:

POST https://api.nexalogy.com/project/create
HTTP Header:"Content-Type" "application/json"
HTTP Header:"api_key" "XXXXXXXXXXXXXXXXXXXX"
HTTP Body:[{"name":"project1","lang":"en","type":"twitter"}]
api_key:XXXXXXXXXXXXXXXXXXXX
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

==== The code: ==== ====代码:====

package servlet;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/AddProject")
public class AddProject extends HttpServlet {
    private static final long serialVersionUID = 1L;
    public AddProject() {
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String body="[{\"name\":\"project1\",\"lang\":\"en\",\"type\":\"twitter\"}]";
        String api_key="XXXXXXXXXXXXXXXXXXXX";
        String str_response="";
        String line="";
        URL url = new URL("https://api.nexalogy.com/project/create?api_key="+api_key);
        try{
            HttpURLConnection connection = (HttpURLConnection)url.openConnection();
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type","application/json");
            System.out.println("POST https://api.nexalogy.com/project/create?api_key="+api_key);
            System.out.println("HTTP Header:"+"\"Content-Type\" \"application/json\"");
            System.out.println("HTTP Body:"+body);
            System.out.println("api_key:"+api_key);
            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
            wr.writeBytes(body);
            wr.flush();
            wr.close();
            InputStream is = connection.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader rd = new BufferedReader(isr);
            while ((line = rd.readLine()) != null) str_response+= line + '\r';
            rd.close();
            System.out.println("str_response:"+str_response);
        }catch(Exception e){
            e.printStackTrace(System.out);
            //throw new RuntimeException(e);
        }
    }
}

==== Complete StackTrace: ==== ====完成StackTrace:====

com.sun.jersey.api.client.ClientHandlerException: 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
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:131)
    at com.sun.jersey.api.client.Client.handle(Client.java:616)
    at com.sun.jersey.api.client.WebResource.handle(WebResource.java:559)
    at com.sun.jersey.api.client.WebResource.post(WebResource.java:230)
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tREST_2Process(Twitter_api_create_project.java:955)
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.tJava_1Process(Twitter_api_create_project.java:635)
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.runJobInTOS(Twitter_api_create_project.java:1641)
    at engine_brandchats.twitter_api_create_project_0_1.Twitter_api_create_project.main(Twitter_api_create_project.java:1494)
Caused by: 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
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(Unknown Source)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler$1$1.getOutputStream(URLConnectionClientHandler.java:203)
    at com.sun.jersey.api.client.CommittingOutputStream.commitWrite(CommittingOutputStream.java:117)
    at com.sun.jersey.api.client.CommittingOutputStream.write(CommittingOutputStream.java:89)
    at sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
    at sun.nio.cs.StreamEncoder.implFlush(Unknown Source)
    at sun.nio.cs.StreamEncoder.flush(Unknown Source)
    at java.io.OutputStreamWriter.flush(Unknown Source)
    at java.io.BufferedWriter.flush(Unknown Source)
    at com.sun.jersey.core.util.ReaderWriter.writeToAsString(ReaderWriter.java:191)
    at com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider.writeToAsString(AbstractMessageReaderWriterProvider.java:128)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:88)
    at com.sun.jersey.core.impl.provider.entity.StringProvider.writeTo(StringProvider.java:58)
    at com.sun.jersey.api.client.TerminatingClientHandler.writeRequestEntity(TerminatingClientHandler.java:305)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler._invoke(URLConnectionClientHandler.java:182)
    at com.sun.jersey.client.urlconnection.URLConnectionClientHandler.handle(URLConnectionClientHandler.java:129)
    ... 7 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
    at sun.security.validator.Validator.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
    ... 35 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
    at java.security.cert.CertPathBuilder.build(Unknown Source)
    ... 41 more

EDITED 2013-06-13 Solution: implements X509TrustManager EDITED 2013-06-13解决方案:实现X509TrustManager

Add the following code ... 添加以下代码......

HttpsURLConnection connection = (HttpsURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
if (connection instanceof HttpsURLConnection) {
    try {
        KeyManager[] km = null;
        TrustManager[] tm = {new RelaxedX509TrustManager()};
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, tm, new java.security.SecureRandom());
        SSLSocketFactory sf = sslContext.getSocketFactory();
        ((HttpsURLConnection)connection).setSSLSocketFactory(sf);
        System.out.println("setSSLSocketFactory OK!");
    }catch (java.security.GeneralSecurityException e) {
        System.out.println("GeneralSecurityException: "+e.getMessage());
    }
}

... and add the following class (implements X509TrustManager) ...并添加以下类(实现X509TrustManager)

class RelaxedX509TrustManager implements X509TrustManager {
    public boolean isClientTrusted(java.security.cert.X509Certificate[] chain){ return true; }
    public boolean isServerTrusted(java.security.cert.X509Certificate[] chain){ return true; }
    public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String input) {}
    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String input) {}
}

Try this 试试这个

public void disableCertificates() {
    TrustManager[] trustAllCerts = new TrustManager[]{
        new X509TrustManager() {

            @Override
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                return null;
            }

            @Override
            public void checkClientTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
            }

            @Override
            public void checkServerTrusted(
                    java.security.cert.X509Certificate[] certs, String authType) {
            }
        }
    };

    // Install the all-trusting trust manager
    try {
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
    }
}

I need deactivate the SSL verification because the security methods is the API KEY that I already have. 我需要停用SSL验证,因为安全方法是我已经拥有的API KEY。

It's not clear how you think the API key (and the security aspect it offers) has anything to do with the security offered by SSL/TLS: they're certainly not addressing the same security aspects. 目前尚不清楚您认为API密钥(以及它提供的安全方面)与SSL / TLS提供的安全性有什么关系:它们肯定无法解决相同的安全问题。 SSL/TLS is about protecting the data transmission from eavesdropping and alteration. SSL / TLS是关于保护数据传输免受窃听和更改。

If you check the server you're trying to contact against this SSL testing service , you'll find that the server requires a client that supports Server Name Indication (SNI): this allows the server to host multiple hosts with different certificates. 如果您检查要尝试与此SSL测试服务联系的服务器,您会发现服务器需要支持服务器名称指示(SNI)的客户端:这允许服务器托管具有不同证书的多个主机。

If your client doesn't support SNI (Java only supports it on the client side from version 7), the requests will be presented with a different certificate than the one indented: it may fail either the certificate verification or the host name verification procedures. 如果您的客户端不支持SNI(Java仅在客户端版本7支持它),则将向请求提供与缩进的证书不同的证书:它可能会使证书验证或主机名验证过程失败。 Disabling either checks makes the connection vulnerable to Man-In-The-Middle attacks. 禁用任一检查都会使连接容易受到Man-In-The-Middle攻击。

  • I'd say the most likely cause for the problem you're having is that you're using a version of Java that doesn't support SNI (eg Java 6). 我说你遇到问题的最可能原因是你使用的是不支持SNI的Java版本(例如Java 6)。

  • It's also possible that the JRE you're using doesn't have this particular CA in its default trust store. 您正在使用的JRE也可能在其默认信任库中没有此特定CA. You could try to get an convert a list of CA certificates you're willing to trust from another source (eg Mozilla bundle, as often recommended with cURL). 您可以尝试从其他来源(例如,经常与cURL推荐的Mozilla捆绑包)转换您愿意信任的CA证书列表。 You may need to understand what CA certificates are first. 您可能需要先了解CA证书。

    As the JSSE reference guide says : 正如JSSE参考指南所说

    IMPORTANT NOTE: The JDK ships with a limited number of trusted root certificates in the /lib/security/cacerts file. 重要说明:JDK在/ lib / security / cacerts文件中附带有限数量的受信任根证书。 As documented in keytool, it is your responsibility to maintain (that is, add/remove) the certificates contained in this file if you use this file as a truststore. 如keytool中所述,如果您将此文件用作信任库,则您有责任维护(即添加/删除)此文件中包含的证书。

    Depending on the certificate configuration of the servers you contact, you may need to add additional root certificate(s). 根据您联系的服务器的证书配置,您可能需要添加其他根证书。 Obtain the needed specific root certificate(s) from the appropriate vendor. 从相应的供应商处获取所需的特定根证书。

Either way: deactivating SSL verification isn't the solution to your problem. 无论哪种方式:停用SSL验证不是您的问题的解决方案。

EDIT: 编辑:

It looks like the service you're trying to use has a certificate issued by StartSSL, which isn't one of the CAs bundled by default with the Oracle JRE apparently. 看起来您尝试使用的服务具有由StartSSL颁发的证书,该证书显然不是Oracle JRE默认捆绑的CA之一。

You'll need to download it from StartSSL (or export it from a trusted bundle you already have, it's called "StartCom ...") and import it into your cacerts store with keytool (or another trust store if you're using a different one): 你需要从StartSSL下载它 (或者从你已经拥有的可靠包中导出它,它被称为“StartCom ...”)并使用keytool(或者如果你使用的是另一个信任存储库)将它导入你的cacerts商店不同的一个):

keytool -import -keystore /path/to/jre/lib/security/cacerts -alias startssl -file startssl.crt

(Adapt the path and the name of the startssl certificate file as required, of course.) (当然,根据需要调整startssl证书文件的路径和名称。)

Please use a certificate with the complete certificate chain. 请使用包含完整证书链的证书。 This means at least the root certificate is needed. 这意味着至少需要根证书。

You only have imported the end certificate of your counterpart and the implementation cannot verify the certificate chain. 您只导入了对应的结束证书,并且实现无法验证证书链。 At least the root certificate is needed. 至少需要根证书。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM