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

时间:2025-02-12 19:17:59
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; import org.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双向证书\\"; // 信任库密码,即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) { } } } }