zoukankan      html  css  js  c++  java
  • Java 使用 Apache 的 HttpClient 组件发送 https 请求

    如果我们直接通过普通的方式对https的链接发送请求,会报一个如下的错误:

    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 sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
        at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1886)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:276)
        at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:270)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1341)
        at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:153)
        at sun.security.ssl.Handshaker.processLoop(Handshaker.java:868)
        at sun.security.ssl.Handshaker.process_record(Handshaker.java:804)
        at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1016)
        at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
        at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
        at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
        at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
        at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
        at java.io.FilterOutputStream.flush(FilterOutputStream.java:140)
        at org.apache.commons.httpclient.methods.StringRequestEntity.writeRequest(StringRequestEntity.java:146)
        at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499)
        at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114)
        at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096)
        at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398)
        at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
        at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
        at com.xxx.yyy.portal.utils.HttpRequest.exeRequest(HttpRequest.java:148)
        at com.xxx.yyy.portal.utils.HttpDemo1.main(HttpDemo1.java:15)
    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(PKIXValidator.java:385)
        at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
        at sun.security.validator.Validator.validate(Validator.java:260)
        at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:326)
        at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231)
        at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:126)
        at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1323)
        ... 20 more
    Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
        at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:196)
        at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:268)
        at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:380)
        ... 26 more

    这个错表示https的链接需要证书验证,普通的方式不能完成https链接的请求。

    直接给出代码,封装成工具类,提供了两种实现方式。

    第一种完成使用Java自身的Api实现;

    第二种使用Apache的httpclient相关jar包实现,注意需要引入apache httpclient的相关依赖包,如下:

    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpmime</artifactId>
        <version>4.2.1</version>
    </dependency>
    <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.3.6</version> </dependency>
    <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.3.1</version> </dependency>

    工具类

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.OutputStreamWriter;
    import java.io.PrintWriter;
    import java.net.URL;
    import java.net.URLConnection;
    import java.security.KeyManagementException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.X509TrustManager;
    
    import org.apache.http.HttpEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.apache.http.util.EntityUtils;
    
    public class HttpRequest {
    
        public static String exeHttpsRequest(String URL, String message, String token) {
            String body = "";
            CloseableHttpClient client = null;
            try {
                // 采用绕过验证的方式处理https请求
                SSLContext sslcontext = createIgnoreVerifySSL();
                // 设置协议http和https对应的处理socket链接工厂的对象
                Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
                        .register("http", PlainConnectionSocketFactory.INSTANCE)
                        .register("https", new SSLConnectionSocketFactory(sslcontext,
                                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))
                        .build();
                PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(
                        socketFactoryRegistry);
                HttpClients.custom().setConnectionManager(connManager);
    
                // 创建自定义的httpclient对象
                client = HttpClients.custom().setConnectionManager(connManager).build();
                // CloseableHttpClient client = HttpClients.createDefault();
    
                // 创建post方式请求对象
                HttpPost httpPost = new HttpPost(URL);
    
                // 指定报文头Content-type、User-Agent
                httpPost.setHeader("Content-type", "application/json");
                httpPost.setHeader("Authorization", "Bearer " + token);
                httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; rv:6.0.2) Gecko/20100101 Firefox/6.0.2");
                StringEntity stringEntity = new StringEntity(message, "UTF-8");
                stringEntity.setContentType("application/json");
    
                httpPost.setEntity(stringEntity);
                // 执行请求操作,并拿到结果(同步阻塞)
                CloseableHttpResponse response = client.execute(httpPost);
    
                // 获取结果实体
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    // 按指定编码转换结果实体为String类型
                    body = EntityUtils.toString(entity, "UTF-8");
                }
    
                EntityUtils.consume(entity);
                // 释放链接
                response.close();
                // System.out.println("body:" + body);
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                try {
                    client.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            return body;
    
        }
    
        private static SSLContext createIgnoreVerifySSL() throws NoSuchAlgorithmException, KeyManagementException {
            SSLContext sc = SSLContext.getInstance("SSLv3");
    
            // 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法
            X509TrustManager trustManager = new X509TrustManager() {
                @Override
                public void checkClientTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                        String paramString) throws CertificateException {
                }
    
                @Override
                public void checkServerTrusted(java.security.cert.X509Certificate[] paramArrayOfX509Certificate,
                        String paramString) throws CertificateException {
                }
    
                @Override
                public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
            };
    
            sc.init(null, new TrustManager[] { trustManager }, null);
            return sc;
        }
    
        private static class TrustAnyTrustManager implements X509TrustManager {
    
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }
    
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[] {};
            }
        }
    
        private static class TrustAnyHostnameVerifier implements HostnameVerifier {
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        }
    
        public static String sendSSLPostRequest(String url, String param) {
            PrintWriter out = null;
            BufferedReader in = null;
            String result = "";
            try {
                // URLEncoder.encode(param,"UTF-8");
    
                URL realUrl = new URL(url);
                URLConnection conn = realUrl.openConnection();
                conn.setRequestProperty("accept", "*/*");
                conn.setRequestProperty("connection", "Keep-Alive");
                conn.setRequestProperty("Encoding", "utf-8");
                conn.setRequestProperty("Charsert", "utf-8");
                conn.setRequestProperty("Content-Type", "application/json");
                conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
                conn.setDoOutput(true);
                conn.setDoInput(true);
                if (conn instanceof HttpsURLConnection) {
                    SSLContext sc = SSLContext.getInstance("SSL");
                    sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
                    ((HttpsURLConnection) conn).setSSLSocketFactory(sc.getSocketFactory());
                    ((HttpsURLConnection) conn).setHostnameVerifier(new TrustAnyHostnameVerifier());
                }
                out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
    
                out.print(param);
                out.flush();
                in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                String line;
                while ((line = in.readLine()) != null) {
                    result += line;
                }
            } catch (Exception e) {
                System.out.println("POST 请求异常!!!" + e);
                e.printStackTrace();
            } finally {
                try {
                    if (out != null) {
                        out.close();
                    }
                    if (in != null) {
                        in.close();
                    }
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
    
            return result;
        }
    }

    全文完。

     

    原文地址:

    https://www.cnblogs.com/poterliu/p/9373478.html

  • 相关阅读:
    unity panel删除drawcall失败导致的残留影像
    c# List的排序
    动画播放一段就禁用
    delegate用法
    ctrl+alt+end 修改桌面密码
    Windows 下curl htpps
    Linux下端口映射工具rinetd
    Linux系统下强制踢掉登录用户
    linux ls 按文件大小排序
    chrome的功能Copy as cURL
  • 原文地址:https://www.cnblogs.com/poterliu/p/9373478.html
Copyright © 2011-2022 走看看