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);

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • idea激活码 mac 2021.023月最新在线激活

    idea激活码 mac 2021.023月最新在线激活,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • TinyXML使用方法[通俗易懂]

    TinyXML使用方法[通俗易懂]TinyXML使用说明  TinyXML是一个C++的XML解析库,网上的评价都不错,是一个轻量级的XML解析库。关于TinyXML使用的文章有很多,而且官方也有完整的文档,这里只是简单把自己使用记录写下来,方便以后查阅。     一个XML文档例子:(文章后面会把这个XML当作例子使用)  <!–test.xml–><Persons><P…

  • 久坐提醒电脑软件_久坐提醒app哪个好

    久坐提醒电脑软件_久坐提醒app哪个好下载废话不多说,先直接给出下载地址介绍久坐的危害不必多言,但工作起来很多时候总是不知不觉一坐几个小时不动地方。去年毕业前闲来无事写了个桌面端的久坐提醒小工具,放到github就没再管过,前些天发现这个仓库有了20个star了,虽然很少,但也蛮有成就感的。于是又有了更新的动力,根据issues里使用者提的建议,做了些小修改,提高了一些使用体验。截图展示…

  • 《画解数据结构》(0 – 1)- 算法时间复杂度[通俗易懂]

    《画解数据结构》(0 – 1)- 算法时间复杂度[通俗易懂]《算法和数据结构》学习前的开胃小文

  • Java static(三) – 静态代码块

    Java static(三) – 静态代码块静态代码块static代码块也叫静态代码块,是在类中独立于类成员的static语句块,可以有多个,位置可以随便放,它不在任何的方法体内JVM加载类时会执行这些静态代码块,如果static代码块有多个,JVM将按照它们在类中出现的先后顺序依次执行它们每个静态代码块只会被执行一次实例说明//父类publicclassParentStatic{privatestaticStringpstr=”父类静态变量”;static{System.o.

  • eplan激活码【2021最新】

    (eplan激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

发表回复

您的电子邮箱地址不会被公开。

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