如何让 Unirest(java) 忽略证书错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23242197/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:29:08  来源:igfitidea点击:

how to make Unirest(java) ignore certificate error

javaapache-httpclient-4.xunirest

提问by Allan Ruin

I am using Unirest (java version) to make GET and POST request.But I encounter a problem when accessing SSL encrypted site , since my program is behind a corporate network and the network admin setup a firewall mapping for me. For example foobar.comis mapped to 56.1.89.12:4444. But when I make request to the address, I will received the following ssl certificate error:

我正在使用 Unirest(java 版本)发出 GET 和 POST 请求。但是在访问 SSL 加密站点时遇到问题,因为我的程序位于公司网络后面,并且网络管理员为我设置了防火墙映射。例如foobar.com映射到56.1.89.12:4444. 但是当我向该地址提出请求时,我会收到以下 ssl 证书错误:

com.mashape.unirest.http.exceptions.UnirestException: javax.net.ssl.SSLException: hostname in certificate didn't match: <56.1.89.12> != <www.foobar.com>
    at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:131)
    at com.mashape.unirest.request.BaseRequest.asString(BaseRequest.java:52)

I see Uniresthas advance configuration to use custom httpclient.So I use

我看到Unirest有使用自定义的高级配置httpclient。所以我使用

Unirest.setHttpClient(MyHttpClient.makeClient());
HttpResponse<String> res = null;
try {
    res = Unirest.get(urlstr).asString();
} catch (UnirestException e) {
    e.printStackTrace();
}
String jsonstr = res.getBody();

the makeClientmethod of MyHttpClientis:

makeClient方法MyHttpClient是:

public static HttpClient makeClient(){
 SSLContextBuilder builder = new SSLContextBuilder();
 CloseableHttpClient httpclient = null;
    try {
        // builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
        builder.loadTrustMaterial(null, new TrustStrategy(){
            public boolean isTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
                return true;
            }
        });
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                builder.build());
        httpclient = HttpClients.custom().setSSLSocketFactory(
                sslsf).build();
        System.out.println("custom httpclient called");
        System.out.println(httpclient);

    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }

return httpclient;
}

the main idea is taken from Ignoring SSL certificate in Apache HttpClient 4.3

主要思想取自Apache HttpClient 4.3 中的忽略 SSL 证书

But still this didn't work.Any suggestions?

但这仍然不起作用。有什么建议吗?

回答by Allan Ruin

This is how I finally solved my problem:

这就是我最终解决我的问题的方法:

public static HttpClient makeClient(){
    SchemeRegistry schemeRegistry = new SchemeRegistry();
    schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    try {
        schemeRegistry.register(new Scheme("https", 443, new MockSSLSocketFactory()));
    } catch (KeyManagementException e) {
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    }
    ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
    DefaultHttpClient httpclient = new DefaultHttpClient(cm);
    return httpclient;
}

I had been scratching for a whole day, I hope this could help someone.

我已经刮了整整一天,我希望这可以帮助某人。

回答by Dimitar II

Unfortunately, Unirest does not have a native way to configure SSL, so providing a custom HttpClient instance looks like the only option. Here is a solution, which does not use deprecated classes (like 'DefaultHttpClient') and works with self-signed certificates:

不幸的是,Unirest 没有配置 SSL 的本机方法,因此提供自定义 HttpClient 实例似乎是唯一的选择。这是一个解决方案,它不使用不推荐使用的类(如“DefaultHttpClient”)并使用自签名证书:

protected void prepareHttpsClient() {
    HttpClientBuilder clientBuilder = HttpClientBuilder.create();
    try {
        String certificateStorage = <<yourCertStorageFileName>>;
        String certificatePassword = <<yourCertStoragePassword>>;
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(
            new File(certificateStorage), certificatePassword.toCharArray(),
            new TrustSelfSignedStrategy()).build();
        SSLConnectionSocketFactory sslFactory = new SSLConnectionSocketFactory(sslContext,
            new String[]{"TLSv1"}, null,
            SSLConnectionSocketFactory.getDefaultHostnameVerifier());
        clientBuilder.setSSLSocketFactory(sslFactory);
    }
    catch (Exception e) {
        throw new IllegalArgumentException("Error configuring server certificates.", e);
    }
    HttpClient httpClient = clientBuilder.build();
    Unirest.setHttpClient(httpClient);
}

回答by Maciej Mioduszewski

 SSLContext sslcontext = SSLContexts.custom()
            .loadTrustMaterial(null, new TrustSelfSignedStrategy())
            .build();

    SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    CloseableHttpClient httpclient = HttpClients.custom()
            .setSSLSocketFactory(sslsf)
            .build();
    Unirest.setHttpClient(httpclient);

this worked for me

这对我有用

回答by Dyno Fu

the certificate error solution is a combination from a few places

证书错误解决方案是几个地方的组合

and a relatively complete example.

和一个比较完整的例子。

import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;

public class XXX {

    private static HttpClient unsafeHttpClient;

    static {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy() {
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();

            unsafeHttpClient = HttpClients.custom().setSSLContext(sslContext)
                    .setSSLHostnameVerifier(new NoopHostnameVerifier()).build();

        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
            e.printStackTrace();
        }
    }

    public static HttpClient getClient() {
        return unsafeHttpClient;
    }

    public static void main(String[] args) {

        try {
            HttpClient creepyClient = RestUnirestClient.getClient();
            Unirest.setHttpClient(creepyClient);

            HttpResponse<JsonNode> response = Unirest.get("https://httpbin.org/get?show_env=1").asJson();
            System.out.println(response.getBody().toString());

        } catch (UnirestException e) {
            e.printStackTrace();
        }
    }
}

回答by Zhang Yunlu

I'm using "com.konghq:unirest-java:2.3.14“

我正在使用“com.konghq:unirest-java:2.3.14”

There is a config now

现在有一个配置

Unirest.config().verifySsl(false);