【fastweixin框架教程3】JAVA进行HTTPS网站访问,PKIX path building failed解决方法

  上几篇文章我们谈到fastweixin使用问题和修改。

  今天的问题就是使用JAVA访问HTTPS网站时候经常出现javax.net.ssl.SSLHandshakeException

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.getInputStream(Unknown Source)  
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)  

  

  对于这个问题,一般采用两种方法:1、导入疼讯网站证书 2、修改代码

 考虑到很多人的服务器并不是自主控制,无法进行第一种方法,导入证书,下面决定修改原框架代码以便适应HTTPS。


package com.fastwixinextend;

import com.github.sd4324530.fastweixin.util.NetWorkCenter;

import java.io.File;
import java.io.IOException;

import java.net.URL;

import java.nio.charset.Charset;

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

import java.util.List;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
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.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * com.github.sd4324530.fastweixin.util.NetWorkCenter 修改版本
 * http://blog.csdn.net/xiaoxian8023/article/details/49865335
 *
 * 将 com.github.sd4324530.fastweixin.util修改 public final class NetWorkCenter
 * extends MyNetWorkCenter {
 *
 * 采用https的访问协议获取新的AccessToken时,总是出现异常: 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 之后在网上找了很多例子,最后摘了一个不需要证书的例子:
 */
public class MyNetWorkCenter {

    /**
     * 默认连接超时时间(毫秒) 由于目前的设计原因,该变量定义为静态的,超时时间不能针对每一次的请求做定制 备选优化方案:
     * 1.考虑是否重新设计这个工具类,每次请求都需要创建一个实例; 2.请求方法里加入超时时间参数
     * 或者说是否没必要定制,10秒是一个比较适中的选择,但有些请求可能就是需要快速给出结果T_T
     */
    public static final int CONNECT_TIMEOUT = 10 * 1000;
    private static final Logger LOG
            = LoggerFactory.getLogger(NetWorkCenter.class);
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    public MyNetWorkCenter() {
        super();
    }

    /**
     * 自定义HTTP响应回调接口,用于兼容jdk6
     *
     * @author peiyu
     * @since 1.1
     */
    //  @FunctionalInterface
    public interface ResponseCallback {

        /**
         * 响应后回调方法
         *
         * @param resultCode 响应结果码,比如200成功,404不存在,500服务器异常等
         * @param resultJson 响应内容,目前支持JSON字符串
         */
        void onResponse(int resultCode, String resultJson);
    }

    /**
     * 标识HTTP请求类型枚举
     *
     * @author peiyu
     * @since 1.0
     */
    public enum RequestMethod {
        /**
         * HTTP GET请求 一般对应的是查询业务接口
         */
        GET,
        /**
         * HTTP POST请求 一般对应的是新增业务接口 只是一般都通用这个请求方式来处理一切接口了T_T
         */
        POST,
        /**
         * HTTP PUT请求,用的太少,暂不支持 一般对应的是更新业务接口
         */
        PUT,
        /**
         * HTTP DELETE请求,用的太少,暂不支持 一般对应的是删除业务接口
         */
        DELETE;
        private static final long serialVersionUID = 1L;
    }

    /**
     * 处理HTTP请求 基于org.apache.http.client包做了简单的二次封装 对于子函数,修改doRequest() String
     * ishttp=url.toLowerCase(); if(ishttp.startsWith("https") ||
     * ishttp.startsWith("HTTPS")) { doRequestSSH(method, url, paramData,
     * fileList, callback); return; }
     *
     * @param method HTTP请求类型
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param fileList 需要一起发送的文件列表
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void doRequestSSH(final RequestMethod method, final String url,
            final String paramData,
            final List<File> fileList,
            final ResponseCallback callback) {
        //如果url没有传入,则直接返回
        if (null == url || url.isEmpty()) {
            LOG.warn("The url is null or empty!!You must give it to me!OK?");
            return;
        }

        //默认期望调用者传入callback函数
        boolean haveCallback = true;
        /*
         * 支持不传回调函数,只输出一个警告,并改变haveCallback标识
                 * 用于一些不需要后续处理的请求,比如只是发送一个心跳包等等
         */
        if (null == callback) {
            LOG.warn("--------------no callback block!--------------");
            haveCallback = false;
        }

        LOG.debug("-----------------请求地址:{}-----------------", url);
        //配置请求参数
        RequestConfig config
                = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(CONNECT_TIMEOUT).build();

        SSLContext sslcontext = null;

        // 设置协议http和https对应的处理socket链接工厂的对象
        try {
            sslcontext = SslUtils.createIgnoreVerifySSL();
        } catch (KeyManagementException e) {
        } catch (NoSuchAlgorithmException e) {
        }
        Registry<ConnectionSocketFactory> socketFactoryRegistry
                = RegistryBuilder.<ConnectionSocketFactory>create().register("http",
                        PlainConnectionSocketFactory.INSTANCE).register("https",
                        new SSLConnectionSocketFactory(sslcontext)).build();
        PoolingHttpClientConnectionManager connManager
                = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        HttpClients.custom().setConnectionManager(connManager);

        //创建自定义的httpclient对象
        HttpClientBuilder HttpClientbuilder = HttpClients.custom().setConnectionManager(connManager);
        HttpClientbuilder.setDefaultRequestConfig(config);
        CloseableHttpClient client = HttpClientbuilder.build();
        //CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
        HttpUriRequest request = null;
        switch (method) {
            case GET:
                String getUrl = url;
                if (null != paramData) {
                    getUrl += "?" + paramData;
                }
                request = new HttpGet(getUrl);
                break;
            case POST:
                LOG.debug("请求入参:");
                LOG.debug(paramData);
                request = new HttpPost(url);
                //上传文件
                if (null != fileList && !fileList.isEmpty()) {
                    LOG.debug("上传文件...");
                    MultipartEntityBuilder builder
                            = MultipartEntityBuilder.create();
                    for (File file : fileList) {
                        //只能上传文件哦 ^_^
                        if (file.isFile()) {
                            FileBody fb = new FileBody(file);
                            builder.addPart("media", fb);
                        } else { //如果上传内容有不是文件的,则不发起本次请求
                            LOG.warn("The target '{}' not a file,please check and try again!",
                                    file.getPath());
                            return;
                        }
                    }
                    if (null != paramData) {
                        builder.addPart("description",
                                new StringBody(paramData, ContentType.APPLICATION_JSON));
                    }
                    ((HttpPost) request).setEntity(builder.build());
                } else //不上传文件的普通请求
                {
                    if (null != paramData) {
                        // 目前支持JSON格式的数据
                        StringEntity jsonEntity
                                = new StringEntity(paramData, ContentType.APPLICATION_JSON);
                        ((HttpPost) request).setEntity(jsonEntity);
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                LOG.warn("-----------------请求类型:{} 暂不支持-----------------",
                        method.toString());
                break;
        }
        CloseableHttpResponse response = null;
        try {
            URL u = new URL(url);
            if ("https".equalsIgnoreCase(u.getProtocol())) {
                SslUtils.ignoreSsl();
            }
            long start = System.currentTimeMillis();
            //发起请求
            response = client.execute(request);
            long time = System.currentTimeMillis() - start;
            LOG.debug("本次请求'{}'耗时:{}ms",
                    url.substring(url.lastIndexOf("/") + 1, url.length()),
                    time);
            int resultCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            //此流不是操作系统资源,不用关闭,ByteArrayOutputStream源码里close也是个空方法-0_0-
            //            OutputStream os = new ByteArrayOutputStream();
            //            entity.writeTo(os);
            //            String resultJson = os.toString();
            String resultJson = EntityUtils.toString(entity, UTF_8);
            //返回码200,请求成功;其他情况都为请求出现错误
            if (HttpStatus.SC_OK == resultCode) {
                LOG.debug("-----------------请求成功-----------------");
                LOG.debug("响应结果:");
                LOG.debug(resultJson);
                if (haveCallback) {
                    callback.onResponse(resultCode, resultJson);
                }
            } else if (haveCallback) {
                LOG.warn("-----------------请求出现错误,错误码:{}-----------------",
                        resultCode);
                callback.onResponse(resultCode, resultJson);
            }
        } catch (ClientProtocolException e) {
            LOG.error("ClientProtocolException:", e);
            LOG.warn("-----------------请求出现异常:{}-----------------",
                    e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
                        e.toString());
            }
        } catch (IOException e) {
            LOG.error("IOException:", e);
            LOG.warn("-----------------请求出现IO异常:{}-----------------",
                    e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
                        e.toString());
            }
        } catch (Exception e) {
            LOG.error("Exception:", e);
            LOG.warn("-----------------请求出现其他异常:{}-----------------",
                    e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR,
                        e.toString());
            }
        } finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }
    }
}

原文件NetWorkCenter 修改如下:

package com.github.sd4324530.fastweixin.util;

import com.fastwixinextend.MyNetWorkCenter.RequestMethod;
import com.fastwixinextend.MyNetWorkCenter.ResponseCallback;

import com.github.sd4324530.fastweixin.api.response.BaseResponse;

import com.fastwixinextend.MyNetWorkCenter;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.HttpClientUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

/**
 * HTTP请求客户端操作类,基于org.apache.http.client包4.4.x版本实现
 */
public final class NetWorkCenter extends MyNetWorkCenter {

    /**
     * 默认连接超时时间(毫秒) 由于目前的设计原因,该变量定义为静态的,超时时间不能针对每一次的请求做定制 备选优化方案:
     * 1.考虑是否重新设计这个工具类,每次请求都需要创建一个实例; 2.请求方法里加入超时时间参数
     * 或者说是否没必要定制,10秒是一个比较适中的选择,但有些请求可能就是需要快速给出结果T_T
     */
    public static final int CONNECT_TIMEOUT = 10 * 1000;
    /**
     * 日志输出组件
     */
    private static final Logger LOG = LoggerFactory.getLogger(NetWorkCenter.class);
    private static final Charset UTF_8 = Charset.forName("UTF-8");

    /**
     * 私有化构造器 不允许外界创建实例
     */
    private NetWorkCenter() {
        LOG.warn("Oh,my god!!!How do you call this method?!");
        LOG.warn("You shouldn't create me!!!");
        LOG.warn("Look my doc again!!!");
    }

    /**
     * 发起HTTP POST同步请求 jdk8使用函数式方式处理请求结果 jdk6使用内部类方式处理请求结果
     *
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void post(String url, String paramData,
            ResponseCallback callback) {
        post(url, paramData, null, callback);
    }

    public static BaseResponse post(String url, String paramData) {
        final BaseResponse[] response = new BaseResponse[]{null};
        post(url, paramData, new ResponseCallback() {
            @Override
            public void onResponse(int resultCode, String resultJson) {
                if (200 == resultCode) {
                    BaseResponse r = JSONUtil.toBean(resultJson, BaseResponse.class);
                    r.setErrmsg(resultJson);
                    response[0] = r;
                } else {//请求本身就失败了
                    response[0] = new BaseResponse();
                    response[0].setErrcode(String.valueOf(resultCode));
                    response[0].setErrmsg("请求失败");
                }
            }
        });
        return response[0];
    }

    /**
     * 发起HTTP POST同步请求 jdk8使用函数式方式处理请求结果 jdk6使用内部类方式处理请求结果
     *
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param fileList 需要一起发送的文件列表
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void post(String url, String paramData, List<File> fileList,
            ResponseCallback callback) {
        doRequest(MyNetWorkCenter.RequestMethod.POST, url, paramData, fileList, callback);
    }

    public static BaseResponse post(String url, String paramData, List<File> fileList) {
        final BaseResponse[] response = new BaseResponse[]{null};
        post(url, paramData, fileList, new ResponseCallback() {
            @Override
            public void onResponse(int resultCode, String resultJson) {
                if (200 == resultCode) {
                    BaseResponse r = JSONUtil.toBean(resultJson, BaseResponse.class);
                    if (StrUtil.isBlank(r.getErrcode())) {
                        r.setErrcode("0");
                    }
                    r.setErrmsg(resultJson);
                    response[0] = r;
                } else {//请求本身就失败了
                    response[0] = new BaseResponse();
                    response[0].setErrcode(String.valueOf(resultCode));
                    response[0].setErrmsg("请求失败");
                }
            }
        });
        return response[0];
    }

    /**
     * 发起HTTP GET同步请求 jdk8使用函数式方式处理请求结果 jdk6使用内部类方式处理请求结果
     *
     * @param url 请求对应的URL地址
     * @param paramMap GET请求所带参数Map,即URL地址问号后面所带的键值对,很蛋疼的实现方式,后续得改进,还没什么好的方案
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    public static void get(String url, Map<String, String> paramMap, ResponseCallback callback) {
        String paramData = null;
        if (null != paramMap && !paramMap.isEmpty()) {
            StringBuilder buffer = new StringBuilder();
            //根据传进来的参数拼url后缀- -!
            for (Map.Entry<String, String> param : paramMap.entrySet()) {
                buffer.append(param.getKey()).append("=").append(param.getValue()).append("&");
            }
            //去掉最后一个&符号
            paramData = buffer.substring(0, buffer.length() - 1);
        }
        doRequest(MyNetWorkCenter.RequestMethod.GET, url, paramData, null, callback);
    }

    public static BaseResponse get(String url) {
        final BaseResponse[] response = new BaseResponse[]{null};
        doRequest(MyNetWorkCenter.RequestMethod.GET, url, null, null, new ResponseCallback() {
            @Override
            public void onResponse(int resultCode, String resultJson) {
                if (200 == resultCode) {
                    BaseResponse r = JSONUtil.toBean(resultJson, BaseResponse.class);
                    if (StrUtil.isBlank(r.getErrcode())) {
                        r.setErrcode("0");
                    }
                    r.setErrmsg(resultJson);
                    response[0] = r;
                } else {//请求本身就失败了
                    response[0] = new BaseResponse();
                    response[0].setErrcode(String.valueOf(resultCode));
                    response[0].setErrmsg("请求失败");
                }
            }
        });
        return response[0];
    }

    /**
     * 处理HTTP请求 基于org.apache.http.client包做了简单的二次封装
     *
     * @param method HTTP请求类型
     * @param url 请求对应的URL地址
     * @param paramData 请求所带参数,目前支持JSON格式的参数
     * @param fileList 需要一起发送的文件列表
     * @param callback
     * 请求收到响应后回调函数,参数有2个,第一个为resultCode,即响应码,比如200为成功,404为不存在,500为服务器发生错误;
     * 第二个为resultJson,即响应回来的数据报文
     */
    private static void doRequest(final RequestMethod method, final String url,
            final String paramData, final List<File> fileList, final ResponseCallback callback) {
        //如果url没有传入,则直接返回
        if (null == url || url.isEmpty()) {
            LOG.warn("The url is null or empty!!You must give it to me!OK?");
            return;
        }
        String ishttp = url.toLowerCase();
        if (ishttp.startsWith("https") || ishttp.startsWith("HTTPS")) {
            doRequestSSH(method, url, paramData, fileList, callback);
            return;
        }
        //默认期望调用者传入callback函数
        boolean haveCallback = true;
        /*
         * 支持不传回调函数,只输出一个警告,并改变haveCallback标识
		 * 用于一些不需要后续处理的请求,比如只是发送一个心跳包等等
         */
        if (null == callback) {
            LOG.warn("--------------no callback block!--------------");
            haveCallback = false;
        }

        LOG.debug("-----------------请求地址:{}-----------------", url);
        //配置请求参数
        RequestConfig config = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT).setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(CONNECT_TIMEOUT).build();
        CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(config).build();
        HttpUriRequest request = null;
        switch (method) {
            case GET:
                String getUrl = url;
                if (null != paramData) {
                    getUrl += "?" + paramData;
                }
                request = new HttpGet(getUrl);
                break;
            case POST:
                LOG.debug("请求入参:");
                LOG.debug(paramData);
                request = new HttpPost(url);
                //上传文件
                if (null != fileList && !fileList.isEmpty()) {
                    LOG.debug("上传文件...");
                    MultipartEntityBuilder builder = MultipartEntityBuilder.create();
                    for (File file : fileList) {
                        //只能上传文件哦 ^_^
                        if (file.isFile()) {
                            FileBody fb = new FileBody(file);
                            builder.addPart("media", fb);
                        } else {//如果上传内容有不是文件的,则不发起本次请求
                            LOG.warn("The target '{}' not a file,please check and try again!", file.getPath());
                            return;
                        }
                    }
                    if (null != paramData) {
                        builder.addPart("description", new StringBody(paramData, ContentType.APPLICATION_JSON));
                    }
                    ((HttpPost) request).setEntity(builder.build());
                } else//不上传文件的普通请求
                {
                    if (null != paramData) {
                        // 目前支持JSON格式的数据
                        StringEntity jsonEntity = new StringEntity(paramData, ContentType.APPLICATION_JSON);
                        ((HttpPost) request).setEntity(jsonEntity);
                    }
                }
                break;
            case PUT:
            case DELETE:
            default:
                LOG.warn("-----------------请求类型:{} 暂不支持-----------------", method.toString());
                break;
        }
        CloseableHttpResponse response = null;
        try {
            long start = System.currentTimeMillis();
            //发起请求
            response = client.execute(request);
            long time = System.currentTimeMillis() - start;
            LOG.debug("本次请求'{}'耗时:{}ms", url.substring(url.lastIndexOf("/") + 1, url.length()), time);
            int resultCode = response.getStatusLine().getStatusCode();
            HttpEntity entity = response.getEntity();
            //此流不是操作系统资源,不用关闭,ByteArrayOutputStream源码里close也是个空方法-0_0-
//            OutputStream os = new ByteArrayOutputStream();
//            entity.writeTo(os);
//            String resultJson = os.toString();
            String resultJson = EntityUtils.toString(entity, UTF_8);
            //返回码200,请求成功;其他情况都为请求出现错误
            if (HttpStatus.SC_OK == resultCode) {
                LOG.debug("-----------------请求成功-----------------");
                LOG.debug("响应结果:");
                LOG.debug(resultJson);
                if (haveCallback) {
                    callback.onResponse(resultCode, resultJson);
                }
            } else if (haveCallback) {
                LOG.warn("-----------------请求出现错误,错误码:{}-----------------", resultCode);
                callback.onResponse(resultCode, resultJson);
            }
        } catch (ClientProtocolException e) {
            LOG.error("ClientProtocolException:", e);
            LOG.warn("-----------------请求出现异常:{}-----------------", e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.toString());
            }
        } catch (IOException e) {
            LOG.error("IOException:", e);
            LOG.warn("-----------------请求出现IO异常:{}-----------------", e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.toString());
            }
        } catch (Exception e) {
            LOG.error("Exception:", e);
            LOG.warn("-----------------请求出现其他异常:{}-----------------", e.toString());
            if (haveCallback) {
                callback.onResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.toString());
            }
        } finally {
            //abort the request
            if (null != request && !request.isAborted()) {
                request.abort();
            }
            //close the connection
            HttpClientUtils.closeQuietly(client);
            HttpClientUtils.closeQuietly(response);
        }
    }

}


package com.fastwixinextend;

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;

public class SslUtils {

    /**
     * 绕过验证
     *
     * @return
     * @throws NoSuchAlgorithmException
     * @throws KeyManagementException
     */
    public 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 void trustAllHttpsCertificates() throws Exception {
        TrustManager[] trustAllCerts = new TrustManager[1];
        TrustManager tm = new miTM();
        trustAllCerts[0] = tm;
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, null);
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    static class miTM implements TrustManager, X509TrustManager {

        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public boolean isServerTrusted(X509Certificate[] certs) {
            return true;
        }

        public boolean isClientTrusted(X509Certificate[] certs) {
            return true;
        }

        public void checkServerTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }

        public void checkClientTrusted(X509Certificate[] certs, String authType)
                throws CertificateException {
            return;
        }
    }

    /**
     * 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
     *
     * @throws Exception
     */
    public static void ignoreSsl() throws Exception {
        HostnameVerifier hv = new HostnameVerifier() {
            public boolean verify(String urlHostName, SSLSession session) {
                System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
                return true;
            }
        };
        trustAllHttpsCertificates();
        HttpsURLConnection.setDefaultHostnameVerifier(hv);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值