httpclient4.x访问https[通俗易懂]

httpclient4.x访问https[通俗易懂]https有单向认证和双向认证之分,单向认证即客户端只会认证服务端,双向认证是客户端需要认证服务端,服务端也需要认证客户端。先说单向认证,浏览器访问服务端,服务端接收请求,会把证书(包含密钥和其他信息)和加密后响应返回给浏览器。如果这个证书不是向第三方权威机构申请的,浏览器会提示证书有问题(使用httpclient访问的话会报错)。如果忽略错误,则浏览器接受证书并解密响应,发送的数据也用此密钥

大家好,又见面了,我是你们的朋友全栈君。

https有单向认证和双向认证之分,单向认证即客户端只会认证服务端,双向认证是客户端需要认证服务端,服务端也需要认证客户端。

先说单向认证,浏览器访问服务端,服务端接收请求,会把证书(包含密钥和其他信息)和加密后响应返回给浏览器。如果这个证书不是向第三方权威机构申请的,浏览器会提示证书有问题(使用httpclient访问的话会报错)。如果忽略错误,则浏览器接受证书并解密响应,发送的数据也用此密钥加密。

双向认证的话,客户端访问服务端也要提供证书,否则服务端拒绝响应。而且如果是自己生产的证书,需要把客户端的证书导入到服务端的信任列表中,否则服务端也会拒绝。

前面说到,如果服务端的证书不是向第三方权威机构申请,使用httpclient访问会报错。解决办法由两种,第一种是将证书导入jre的密钥库的信任列表;第二种是让他不去验证服务端证书。如果需要双向认证,还需要为httpclient指定客户端需要使用的证书。


package cloudolp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.conn.ssl.SSLSocketFactory;
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.ssl.SSLContexts;
import org.apache.http.ssl.TrustStrategy;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
 * 
 */
public class HttpClientFactory {
    private static CloseableHttpClient httpClient;

    public synchronized static CloseableHttpClient getCloseableHttpClient(){
        if(httpClient==null){
            SSLConnectionSocketFactory sslConnectionSocketFactory=null;
            try{
                FileInputStream keyin = new FileInputStream(new File("d:\\client.p12"));
                KeyStore keystore = KeyStore.getInstance("PKCS12");
                keystore.load(keyin, "client1".toCharArray());
                keyin.close();
                final TrustStrategy trustStrategy=new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;
                    }
                };
                SSLContext sslcontext = SSLContexts.custom()
                        .loadTrustMaterial(trustStrategy)
                        .loadKeyMaterial(keystore, "client1".toCharArray())
                        .build();
                sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                        sslcontext,
                        SSLConnectionSocketFactory.getDefaultHostnameVerifier());

            } catch(Exception e){
                LogFactory.getLog(HttpClientFactory.class).error(e);
            }
            Registry<ConnectionSocketFactory> registry= RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("http", PlainConnectionSocketFactory.getSocketFactory())
                    .register("https", sslConnectionSocketFactory)
                    .build();
            PoolingHttpClientConnectionManager connectionManager=new PoolingHttpClientConnectionManager(registry);
            connectionManager.setMaxTotal(200);
            connectionManager.setDefaultMaxPerRoute(20);
            HttpClientBuilder httpClientBuilder=HttpClients.custom();
//            if(sslConnectionSocketFactory!=null){
//                httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory);
//            }
            httpClientBuilder.setConnectionManager(connectionManager);
            httpClient = httpClientBuilder.build();
        }
        return httpClient;
    }
}


final TrustStrategy trustStrategy=new TrustStrategy() {
                    @Override
                    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                        return true;
                    }
                };

自己实现证书信任策略,这里我们之间返回true,这样所有的服务端证书都会被信任,这样如果服务端的证书不是权威机构颁布的,httclient就不会报错了

SSLContext sslcontext = SSLContexts.custom()
                        .loadTrustMaterial(trustStrategy)
                        .loadKeyMaterial(keystore, "client1".toCharArray())
                        .build();

loadTrustMaterial()是设置服务端证书的信任策略,这个方法有很多重载的方法,比如可以使用密钥库

loadKeyMaterial()设置客户端需要发送到服务端的证书,有两个参数,密钥库和密钥密码,密钥库是client1.p12,keystore.load()也有两个参数,一个是真
正的存储地址,一个是密钥库的秘密(有可能和密钥的秘密不一样)。这里的证书类型是PKCS12,是个人证书。

FileInputStream keyin = new FileInputStream(new File("d:\\client.p12"));
                KeyStore keystore = KeyStore.getInstance("PKCS12");
                keystore.load(keyin, "client1".toCharArray());

最后通过SSLContext 创建套接字连接工厂,并注册到连接管理器。

注意我是用的CloseableHttpClient和PoolingHttpClientConnectionManager

如果用的是DefaultHttpClient,可以用下面这段代码

HttpClient httpClient = new DefaultHttpClient(); 
SSLSocketFactory socketFactory = new SSLSocketFactory(sslContext); 
Scheme sch = new Scheme(“https”, 8443, socketFactory); 
httpClient.getConnectionManager().getSchemeRegistry().register(sch);

但如果用的不是DefaultHttpClient,而是CloseableHttpClient,代码ttpClient.getConnectionManager().getSchemeRegistry().register(sch)会报错,在实际中应该很少会使用DefaultHttpClient。

如果没有设置连接管理器,则可在builder中设置套接字连接工厂

httpClientBuilder.setSSLSocketFactory(sslConnectionSocketFactory);

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/163258.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • RowBounds实现分页[通俗易懂]

    RowBounds实现分页[通俗易懂]但使用RowBounds后,会将id>0的所有数据都加载到内存中,然后跳过offset=3条数据,截取10条数据出来,若id>0的数据有100万,则100w数据都会被加载到内存中,从而。

    2022年9月22日
    3
  • IDEA 非maven项目打jar包(包含第三方依赖包)

    IDEA 非maven项目打jar包(包含第三方依赖包)**IDEA非maven项目打jar包**普通java项目打JAR包方式(包含第三方依赖包):①在保证程序能运行情况下:②③④***最后就生成JAR包了在相应文件夹下运行控制台命令java-jar.jar就可以运行了…

    2022年6月19日
    73
  • tcpdump抓包命令详解_tcpdump抓udp包命令详解

    tcpdump抓包命令详解_tcpdump抓udp包命令详解tcpdump

    2022年8月20日
    16
  • 土地利用转移矩阵怎么做_土地利用转移矩阵年份怎么看

    土地利用转移矩阵怎么做_土地利用转移矩阵年份怎么看一、2000年-2005年土地利用转移矩阵1、转换工具-由栅格转出-栅格转面:grid转shp2、合并之后,属性表添加字段:类型和面积(一定要带年份,方便后续处理)3、DataManagementTools→Generalization→Dissolve数据管理工具-制图综合-融合(选择年份+类型名称、面积)4、AnalysisTools→Overlay→Intersect分析工具-叠加分析-相交5、生成结果之后打开属性表,添加字段为newarea,计算几何,然后导出结

    2025年5月28日
    5
  • iReport自定义快捷键「建议收藏」

    iReport自定义快捷键「建议收藏」设置方法:工具-选项-快捷键映射预览CTRL+D工具-选项-快捷键映射-designer-runreport编辑sql语句ALT+A工具-选项-快捷键映射-designer-editorReportqueryadapttopartentheight快捷键ALT+S页面设计ALT+D适应band的宽度ALT+F顶部对齐ALT+G左对齐ALT+H子报表参考ALT

    2025年10月20日
    3
  • ArcGIS二次开发基础教程(00):基础界面设计

    ArcGIS二次开发基础教程(00):基础界面设计ArcGIS二次开发基础教程(00):基础界面设计(开发环境:VS2010+ArcEngine10.2+C#;鉴于学习ArcGIS二次开发的同学都有一定的WinForm开发和ArcGIS软件使用基础,故此教程不再对一些基础内容作详细阐述)首先新建一个Windows窗体应用程序,设置Size为(700,450),再添加一个MenuStrip,输入文件,如图:添加一个ToolB…

    2022年7月23日
    13

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号