HttpClient的ssl方式发送请求

最近因为项目需要,需要以rest方式和第三方平台交互,由于需要ssl方式连接,所以记录一下:

maven依赖如下:

        <dependency>
			<groupId>org.apache.httpcomponents</groupId>
			<artifactId>httpclient</artifactId>
			<version>4.5.3</version>
		</dependency>

这里介绍两种ssl连接方式,一种是ssl信任所有的证书(基本上也就是没有安全性保证),另一种是ssl的正常使用(需要证书认证的)
首先是一个工具类


2019/4/3补充,前段时间,部署到生产环境后发生了一点问题,观察服务器日志(websphere)发现是报告线程挂起,通过查询google,发现是因为建立http连接后,没有关闭资源 ,造成资源耗尽,今天重新编辑此文

主要 增加了资源池对象 HttpClientConnectionManager

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.X509TrustManager;

public class HttpsTrustManager implements X509TrustManager {

	@Override
	public void checkClientTrusted(X509Certificate[] arg0, String arg1)
			throws CertificateException {
		// TODO Auto-generated method stub

	}

	@Override
	public void checkServerTrusted(X509Certificate[] arg0, String arg1)
			throws CertificateException {
		// TODO Auto-generated method stub

	}

	@Override
	public X509Certificate[] getAcceptedIssuers() {
		return new X509Certificate[]{};
	}

}

正常SSL方式(需要证书)的工厂类

package com.haitaiinc.orionmonitor.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
/**
 * 构建httpclient的
 * @author Think
 *
 */
public class HttpClientFactory {

	
		
	private static CloseableHttpClient client;
	//连接池 
	private static  HttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
	
	
	  /**
     * 获取需要安全认证的httpClient的实例
     * @Title: getHttpsClient 
     * @Description: TODO
     * @Author: Think
     * @Date :Jan 16, 2019
     * @return: HttpClient
     */
    public static CloseableHttpClient getHttpsClient() throws Exception {

        if (client != null) {
            return client;
        }
        SSLContext sslcontext = getSSLContext();
        SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        
        client = HttpClients.custom().setConnectionManager(poolingConnManager).setSSLSocketFactory(factory).build();

        return client;
    }

    private static SSLContext getSSLContext() throws KeyStoreException, 
    NoSuchAlgorithmException, CertificateException, IOException, KeyManagementException {
        KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
        
        Map<String, String> map = ParseSSLUtil.getInterfaceConfig();
        String keyLocation = map.get("keystore");
        
        FileInputStream instream = new FileInputStream(new File(keyLocation));
        try {
            trustStore.load(instream, "changeit".toCharArray());
        } finally {
            instream.close();
        }
        return SSLContexts.custom()
                .loadTrustMaterial(trustStore)
                .build();
    }
    
    public static void releaseInstance() {
        client = null;
    }
    
    
}


不安全的SSL方式的工厂类

package com.haitaiinc.orionmonitor.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.X509TrustManager;

import org.apache.http.client.HttpClient;
import org.apache.http.conn.HttpClientConnectionManager;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;

public class HttpClientFactoryWithNoSSL {

	private static CloseableHttpClient client;
	
	
	//连接池 
	private static  HttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
    /**
	 * 获取不需要ssl认证的httpClient实例
	 * @Title: getHttpsClientWithNoCert 
	 * @Description: TODO
	 * @Author: Think
	 * @Date :Jan 16, 2019
	 * @return: HttpClient
	 */
    public static HttpClient getHttpsClient() throws Exception {

        if (client != null) {
            return client;
        }
        SSLContext sslcontext = SSLContexts.custom().useSSL().build();
        sslcontext.init(null, new X509TrustManager[]{new HttpsTrustManager()}, new SecureRandom());
        SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
                SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
        client = HttpClients.custom().setConnectionManager(poolingConnManager).setSSLSocketFactory(factory).build();

        return client;
    }

    public static void releaseInstance() {
        client = null;
    }
}


使用样例:

     
    	

        //获取httpclient客户端
    	CloseableHttpClient httpsClient = HttpClientFactory.getHttpsClient();
    	//因为需要认证就是需要将{用户名:密码}变成字节数组并base64编码
		byte[] admin= ParseSSLUtil.getUserTokenString().getBytes();
		String encoding = ParseSSLUtil.encodeBase64(admin);
		
		//内存使用情况
		HttpGet httpGet = new HttpGet(config.get("url").concat("/api/statistics/memoryusage"));
		
		httpGet.addHeader("Content-Type", "application/json");
		httpGet.setHeader("Authorization", "Basic " + encoding);
		String mem = "";
		CloseableHttpResponse responseMem = null;
		CloseableHttpResponse responseCPU = null;
		CloseableHttpResponse responseDisk = null;
		try {
			responseMem = httpsClient.execute(httpGet);
			if(responseMem.getStatusLine().getStatusCode()!=HttpStatus.SC_OK){
				mem = "0";
			}else{
				HttpEntity entity = responseMem.getEntity();
				if(entity != null){
		            mem = EntityUtils.toString(entity,"UTF-8");
		        }
				EntityUtils.consume(entity);//要消耗消息实体,这是必须步骤
			}
		} catch (Exception e1) {
			e1.printStackTrace();
			mem = "0";
		}finally{
			responseMem.close();//尝试关闭资源,将socket连接返回给资源池
		}

你可能感兴趣的:(java类库,httpclient,ssl)