https实现双向验证请求

来源:互联网 发布:淘宝缩水女 编辑:程序博客网 时间:2024/05/21 22:49

前言:

1、 某一次调上游接口过程中,测试环境用http,但生产环境需要用https,故将http改造成https,记录在此,以便之后参考;

2、https比http更安全,http明文传输,https密文传输;

3、https三次服务器握手,先验证服务器的可信性,然后进行数据加密传输;

4、该实例继承httpclient实现https通讯;

5、TLS是SSL 3.0的升级版;

https相关文件说明:

1、xxx.keystore // 服务器证书库,配置在web服务端,tomcat的server.xml中;

2、xxxTrust.keystore // 客户端信任证书库,由服务端证书生产;

3、*.cer // 客户端证书,由客户端证书库导出;

4、*.cer // 服务端证书,由服务端证书库导出;

5、客户端证书库、服务器证书库都设置,表示双向验证,如果只传其中一个,表示单向数据传输验证;

6、https与http的代码不同之处,在于sslContext的获取;

相关jar包:

<dependency>
    <groupId>commons-httpclient</groupId>
    <artifactId>commons-httpclient</artifactId>
    <version>3.1</version>
</dependency>

代码说明:

本实例只实现了https双向验证中的客户端验证,具体服务器端的验证和配置(主要是web服务器配置)这里不涉及

代码如下:

import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.UnsupportedEncodingException;import java.nio.charset.Charset;import java.security.KeyStore;import java.security.KeyStoreException;import java.security.NoSuchAlgorithmException;import java.security.SecureRandom;import java.security.cert.CertificateException;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Set;import javax.net.ssl.KeyManager;import javax.net.ssl.KeyManagerFactory;import javax.net.ssl.SSLContext;import javax.net.ssl.TrustManager;import javax.net.ssl.TrustManagerFactory;import org.apache.commons.lang.StringUtils;import org.apache.http.HttpEntity;import org.apache.http.HttpStatus;import org.apache.http.NameValuePair;import org.apache.http.StatusLine;import org.apache.http.client.ClientProtocolException;import org.apache.http.client.config.RequestConfig;import org.apache.http.client.entity.UrlEncodedFormEntity;import org.apache.http.client.methods.CloseableHttpResponse;import org.apache.http.client.methods.HttpPost;import org.apache.http.conn.ssl.SSLConnectionSocketFactory;import org.apache.http.entity.ByteArrayEntity;import org.apache.http.entity.ContentType;import org.apache.http.entity.mime.HttpMultipartMode;import org.apache.http.entity.mime.MultipartEntityBuilder;import org.apache.http.impl.client.CloseableHttpClient;import org.apache.http.impl.client.HttpClients;import org.apache.http.message.BasicNameValuePair;import org.apache.http.util.EntityUtils;public class HttpsUtil {/** * 默认字符集 */private static final String defaultCharset = "UTF-8";/** * 连接超时时间 */private final static int connectionTimeout = 6000;/** * socket超时时间 */private final static int soTimeout = 10000;// 主秘钥绝对路径private static final String keystore = "xxx.keystore";// 主密钥密码private static final String keystorePassword = "xxxxxx";// 信任密钥绝对路径private static final String truststore = "xxxTrust.keystore";// 信任密钥密码private static final String truststorePassword = "xxxxxx";private static SSLContext sslContext;/** * 从给定的路径中加载此 KeyStore *  * @param filePath *            keystore 文件绝对路径 * @param password *            keystore 访问密钥 * @return keystore 对象 */private static KeyStore createKeyStore(final String filePath,final String password) throws KeyStoreException,NoSuchAlgorithmException, CertificateException, IOException {if (filePath == null) {throw new IllegalArgumentException("证书路径为空!");}KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());InputStream is = null;try {// is = new FileInputStream(new File(filePath));is = HttpsUtil.class.getResourceAsStream(filePath);keystore.load(is, password != null ? password.toCharArray() : null);} finally {if (is != null) {is.close();is = null;}}return keystore;}/** * Post方式提交,URL中不包含提交参数, 格式:http://www.g.cn *  * @param url *            提交地址 * @param content *            提交内容 * @return 响应消息 */public static String post(String url, String content) {return post(url, content, null);}/** * Post方式提交 *  * @param url *            请求地址 * @param content *            请求内容,可为空 * @param charset *            字符集 * @return */public static String post(String url, String content, String charset) {if (StringUtils.isBlank(url)) {return null;}if (charset == null) {charset = defaultCharset;}CloseableHttpClient httpclient = getHttpClient();ByteArrayEntity entity = null;HttpPost httpPost = null;String result = null;try {httpPost = new HttpPost(url);if (!StringUtils.isBlank(content)) {entity = new ByteArrayEntity(content.getBytes(charset));httpPost.setEntity(entity);}CloseableHttpResponse httpResponse = httpclient.execute(httpPost);StatusLine status = httpResponse.getStatusLine();HttpEntity httpEntity = httpResponse.getEntity();result = EntityUtils.toString(httpEntity);if (status.getStatusCode() == HttpStatus.SC_OK) {System.out.println("服务器返回【正常】:" + result);} else {System.out.println("服务器返回【异常】:" + result);return null;}} catch (IOException e) {e.printStackTrace();} finally {if (httpclient != null) {try {httpclient.close();} catch (IOException e) {e.printStackTrace();}}}return result;}/** * Post方式提交,URL中不包含提交参数, 格式:http://www.g.cn *  * @param url *            提交地址 * @param params *            提交参数集, 键/值对 * @return 响应消息 */public static String post(String url, Map<String, String> params) {return post(url, params, null);}/** * Post方式提交,URL中不包含提交参数, 格式:http://www.g.cn *  * @param url *            提交地址 * @param params *            提交参数集, 键/值对 * @param charset *            参数提交编码集 * @return 响应消息 */public static String post(String url, Map<String, String> params,String charset) {if (StringUtils.isBlank(url)) {return null;}if (charset == null) {charset = defaultCharset;}CloseableHttpClient httpclient = getHttpClient();String result = null;UrlEncodedFormEntity formEntity = null;try {if (StringUtils.isBlank(charset)) {formEntity = new UrlEncodedFormEntity(getParamsList(params));} else {formEntity = new UrlEncodedFormEntity(getParamsList(params),charset);}} catch (UnsupportedEncodingException e) {e.printStackTrace();return null;}HttpPost httpPost = new HttpPost(url);httpPost.setEntity(formEntity);try {CloseableHttpResponse httpResponse = httpclient.execute(httpPost);StatusLine status = httpResponse.getStatusLine();HttpEntity httpEntity = httpResponse.getEntity();result = EntityUtils.toString(httpEntity);if (status.getStatusCode() == HttpStatus.SC_OK) {System.out.println("服务器返回【正常】:" + result);} else {System.out.println("服务器返回【异常】:" + result);return null;}} catch (ClientProtocolException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (httpclient != null) {try {httpclient.close();} catch (IOException e) {e.printStackTrace();}}}return result;}/** * 将传入的键/值对参数转换为NameValuePair参数集 *  * @param paramsMap *            参数集, 键/值对 * @return NameValuePair参数集 */private static List<NameValuePair> getParamsList(Map<String, String> paramsMap) {if (paramsMap == null || paramsMap.size() == 0) {return null;}List<NameValuePair> params = new ArrayList<NameValuePair>();for (Map.Entry<String, String> map : paramsMap.entrySet()) {params.add(new BasicNameValuePair(map.getKey(), map.getValue()));}return params;}/** * form请求,上传图片 *  * @param datas *            普通数据map * @param files *            图片map * @param uploadUrl *            上传图片的地址 */public static String postForm(Map<String, String> datas,Map<String, String> files, String uploadUrl) {CloseableHttpClient httpclient = getHttpClient();HttpPost httpPost = new HttpPost(uploadUrl);String result = "";RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(soTimeout).setConnectTimeout(connectionTimeout).build();httpPost.setConfig(requestConfig);MultipartEntityBuilder multipartEntityBuilder = MultipartEntityBuilder.create();multipartEntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);multipartEntityBuilder.setCharset(Charset.forName(defaultCharset));Set<Map.Entry<String, String>> setData = datas.entrySet();Iterator<Map.Entry<String, String>> iterator = setData.iterator();// 文本while (iterator.hasNext()) {Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next();multipartEntityBuilder.addTextBody(entry.getKey(),entry.getValue(),ContentType.create("text/plain",Charset.forName(defaultCharset)));}// 发送的文件if (files != null) {iterator = files.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next();String path = entry.getValue();if ("".equals(path) || path == null)continue;File file = new File(entry.getValue());// addBinaryBody还支持字节流、文件流multipartEntityBuilder.addBinaryBody(entry.getKey(), file);}}CloseableHttpResponse response = null;HttpEntity httpEntity = multipartEntityBuilder.build();httpPost.setEntity(httpEntity);try {response = httpclient.execute(httpPost);StatusLine status = response.getStatusLine();HttpEntity entity = response.getEntity();result = EntityUtils.toString(entity);if (status.getStatusCode() == HttpStatus.SC_OK) {System.out.println("服务器返回【正常】:" + result);} else {System.out.println("服务器返回【异常】:" + result);return null;}} catch (ClientProtocolException e) {e.printStackTrace();} catch (UnsupportedEncodingException e1) {e1.printStackTrace();} catch (IOException e) {e.printStackTrace();} finally {if (httpclient != null) {try {httpclient.close();} catch (IOException e) {e.printStackTrace();}}}return result;}/** * 获取httpclient *  * @return */private static CloseableHttpClient getHttpClient() {if (sslContext == null) {try {// 客户端秘钥管理器KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");kmf.init(createKeyStore(keystore, keystorePassword),keystorePassword.toCharArray()); // init()验证数据KeyManager[] keyManagers = kmf.getKeyManagers();// 服务端秘钥管理器TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");trustManagerFactory.init(createKeyStore(truststore,truststorePassword));TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();sslContext = SSLContext.getInstance("TLS");sslContext.init(keyManagers, trustManagers, new SecureRandom());} catch (Exception e) {System.out.println("获取ssl证书异常!");e.printStackTrace();return null;}}SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);return HttpClients.custom().setSSLSocketFactory(sslsf).build();}}