资讯详情

Java-HttpClient通过证书实现SSL双向认证(客户端)

2022-07-25:修复一个bug(javax.net.ssl.SSLPeerUnverifiedException: Certificate for <xx.xxx.xxx.xxx> doesn’t match any of the subject) 修改内容如下:

SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(     sslContext,     NoopHostnameVerifier.INSTANCE); 

最近,我们需要将我们的数据推送到第三方服务器,因此需要使用它SSL双向认证,中间搜索了一些资料,发现都不是很完美,所以整理了一些别人的资料。

首先是第三方提供的根证和客户端密钥: 根证书:ca.crt 客户端密钥:client.p12 客户端证书密码123456

第一步:用根证书生成信任库文件 将根证书ca.crt复制到jdk的jre\lib\security(如:C:\Program Files\Java\jdk1.8.0_91\jre\lib\security) 打开电脑CMD命令窗口执行以下命令(在这里使用)jdk自带keytool工具) test.truststore、DemoCA和密码123456是自定义的,这个密码需要记住后面的加载证书

keytool -keystore test.truststore -keypass 123456 -storepass 123456 -alias DemoCA -import -trustcacerts -file ca.cer 

最终在security在目录下生成一个test.truststore文件

第二步:处理HttpClient加载证书 直接在这里上代码 因为我只需要向第三方推送数据和上传文件,所以我只写了两个post请求方法

import org.apache.http.HttpEntity; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; 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.StringEntity; importorg.apache.http.entity.mime.MultipartEntity;
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 javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.security.*;
import java.security.cert.CertificateException;
import java.util.Map;

/** * Sakura */
public class SSLHttpClientUtil { 
       

	// 客户端证书路径,用了本地绝对路径,需要修改
	private final static String CLIENT_CERT_FILE = "E:\\Desktop\\测试环境通讯SSL双向证书\\client.p12";
	// 客户端证书密码
	private final static String CLIENT_PWD = "123456";
	// 信任库路径,即keytool生成的那个自定义名称的库文件
	private final static String TRUST_STRORE_FILE = "E:\\Desktop\\测试环境通讯SSL双向证书\\test.truststore";
	// 信任库密码,即keytool时的密码
	private final static String TRUST_STORE_PWD = "123456";


	/** * 获取HttpClient客户端 * * @return */
	public static CloseableHttpClient getHttpClient() { 
       
		SSLConnectionSocketFactory sslSocketFactory;
		try { 
       
			sslSocketFactory = getSocketFactory();
		} catch (Exception e) { 
       
			throw new RuntimeException(e);
		}
		CloseableHttpClient httpClient = HttpClientBuilder.create().setSSLSocketFactory(sslSocketFactory).build();
		return httpClient;
	}

	/** * 创建SSLSocketFactory实例 * * @return * @throws CertificateException * @throws NoSuchAlgorithmException * @throws KeyStoreException * @throws IOException * @throws KeyManagementException * @throws UnrecoverableKeyException */
	private static SSLConnectionSocketFactory getSocketFactory()
			throws CertificateException, NoSuchAlgorithmException, KeyStoreException,
			IOException, KeyManagementException, UnrecoverableKeyException { 
       
		// 初始化密钥库
		KeyManagerFactory keyManagerFactory = KeyManagerFactory
				.getInstance("SunX509");
		KeyStore keyStore = getKeyStore(CLIENT_CERT_FILE, CLIENT_PWD, "PKCS12");
		keyManagerFactory.init(keyStore, CLIENT_PWD.toCharArray());
		// 初始化信任库
		KeyStore trustKeyStore = getKeyStore(TRUST_STRORE_FILE, TRUST_STORE_PWD, "JKS");
		TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
		trustManagerFactory.init(trustKeyStore);
		// 加载协议
		SSLContext sslContext = SSLContext.getInstance("SSL");
		sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
		//return new SSLConnectionSocketFactory(sslContext);
		SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
				sslContext,
				NoopHostnameVerifier.INSTANCE);

		return sslConnectionSocketFactory;
	}

	/** * 获取(密钥及证书)仓库 * * @param keyStorePath 证书路径 * @param password 证书密码 * @param type 证书类型 * @return * @throws KeyStoreException * @throws CertificateException * @throws IOException * @throws NoSuchAlgorithmException */
	private static KeyStore getKeyStore(String keyStorePath, String password, String type)
			throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException { 
       
		// 获取证书
		FileInputStream inputStream = new FileInputStream(keyStorePath);
		// 秘钥仓库
		KeyStore keyStore = KeyStore.getInstance(type);
		keyStore.load(inputStream, password.toCharArray());
		inputStream.close();
		return keyStore;
	}

	/** * post请求发送json格式参数 * * @param url * @param strBody * @return * @throws Exception */
	public static String HttpPostByJson(String url, String strBody) throws Exception { 
       
		CloseableHttpClient httpClient = getHttpClient();
		CloseableHttpResponse response = null;
		String resultMsg = "";
		try { 
       
			HttpPost httpPost = new HttpPost(url);
			httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
			httpPost.setHeader("Accept", "application/json");

			StringEntity se = new StringEntity(strBody, Charset.forName("UTF-8"));
			se.setContentType("text/json");

			httpPost.setEntity(se);

			response = httpClient.execute(httpPost);
			HttpEntity entity;
			entity = response.getEntity();
			resultMsg = EntityUtils.toString(entity, "UTF-8");
		} catch (Exception e) { 
       
			e.printStackTrace();
		} finally { 
       
			try { 
       
				if (response != null) { 
       
					response.close();
				}
				httpClient.close();
			} catch (IOException e) { 
       
				e.printStackTrace();
			}
		}

		return resultMsg;
	}

	/** * post请求发送form表单文件及参数 * * @param url * @param map * @param file * @return * @throws RuntimeException */
	public static String sendHttpMessage(String url, Map<String, String> map, File file) throws RuntimeException { 
       
		CloseableHttpClient httpClient = getHttpClient();
		CloseableHttpResponse response = null;
		try { 
       
			if (StringUtils.isEmpty(url) || null == map || map.isEmpty()) { 
       
				return null;
			}
			//创建POST请求
			HttpPost post = new HttpPost(url);
			MultipartEntity entity = new MultipartEntity();
			//请求参数
			for (String key : map.keySet()) { 
       
				entity.addPart(key, new StringBody(map.get(key), Charset.forName("UTF-8")));
			}
			entity.addPart("file", new FileBody(file));
			post.setEntity(entity);

			response = httpClient.execute(post);
			if (response.getStatusLine().getStatusCode() != HttpStatus.SC_OK) { 
       
				throw new RuntimeException("请求失败!");
			}

			HttpEntity resEntity = response.getEntity();
			return null == resEntity ? "" : EntityUtils.toString(resEntity, "GBK");
		} catch (UnknownHostException e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (UnsupportedEncodingException e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (ClientProtocolException e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (IOException e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (Exception e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} finally { 
       
			try { 
       
				if (response != null) { 
       
					response.close();
				}
				httpClient.close();
			} catch (IOException e) { 
       
				e.printStackTrace();
			}
		}
	}

	/** * 获取线上文件 * @param destUrl * @param outputfilePath */
	public static void saveToFile(String destUrl, String outputfilePath) { 
       
		FileOutputStream fos = null;
		BufferedInputStream bis = null;
		HttpURLConnection httpUrl = null;
		URL url;
		int BUFFER_SIZE = 1024;
		byte[] buf = new byte[BUFFER_SIZE];
		int size;
		try { 
       
			url = new URL(destUrl);
			httpUrl = (HttpURLConnection) url.openConnection();
			httpUrl.connect();
			bis = new BufferedInputStream(httpUrl.getInputStream());
			fos = new FileOutputStream(outputfilePath);
			while ((size = bis.read(buf)) != -1) { 
       
				fos.write(buf, 0, size);
			}
			fos.flush();
		} catch (IOException e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} catch (ClassCastException e) { 
       
			e.printStackTrace();
			throw new RuntimeException(e.getMessage());
		} finally { 
       
			try { 
       
				fos.close();
				bis.close();
				httpUrl.disconnect();
			} catch (IOException e) { 
       
			} catch (NullPointerException e) { 
       
			}
		}
	}
}

第三步:测试方法

    public static void main(String[] args) throws Exception { 
       
		JSONObject json = new JSONObject();
		json.put("name", "z3");

		String strReturn1 = SSLHttpClientUtil.HttpPostByJson("http://localhost:8230/api", json.toJSONString());
		System.out.println(strReturn1);

		File temporaryFile = new File("E:\\Desktop\\图片\\123.jpg");
		Map<String, String> map = new HashMap<>();
		map.put("name", "z3");
		map.put("sex", "男");

		String strReturn2 = SSLHttpClientUtil.sendHttpMessage("http://localhost:8230/api", map, temporaryFile);
		System.out.println(strReturn2);
	}

标签: sunx电涡流位移传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台