在上一篇springboot学习记录之RestTemplate中,我们知道了:
- 如何创建RestTemplate实例
- 如何通过spring管理RestTemplate
- 如何使用RestTemplate。
在这篇文章中我们将重点说下如何来用https实现ssl请求。
应用场景:微信支付之企业付款接口
文档中提到:请求需要双向证书。 详见证书使用
微信给我们颁发了pfx证书:apiclient_cert.p12
这个时候我们不能像往常一样直接通过
RestTemplate restTemplate = new RestTemplate();
restTemplate.postForObject(url,T.class);
来实现请求并获得结果,我们需要设置ssl相关信息及参数。
微信官方实例:
这个版本是基于httpcomponents 4.3.1 。pom 文件如下:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.1</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
private String ssl(String url, String data) {
//HttpsRequest
StringBuffer message = new StringBuffer();
try {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File("证书地址"));
keyStore.load(instream, "支付商户号".toCharArray());
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, "支付商户号".toCharArray())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
HttpPost httpost = new HttpPost(url);
httpost.addHeader("Connection", "keep-alive");
httpost.addHeader("Accept", "*/*");
httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
httpost.addHeader("Host", "api.mch.weixin.qq.com");
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
httpost.addHeader("Cache-Control", "max-age=0");
httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
httpost.setEntity(new StringEntity(data, "UTF-8"));
CloseableHttpResponse response = httpclient.execute(httpost);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
String text;
while ((text = bufferedReader.readLine()) != null) {
message.append(text);
}
}
EntityUtils.consume(entity);
} catch (IOException e) {
e.printStackTrace();
} finally {
response.close();
}
} catch (Exception e1) {
e1.printStackTrace();
}
return message.toString();
}
那么我们如何用RestTemplate 来实现呢:
我这边使用的是httpcomponents 最新版4.5.3:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
构建httpclient参数的时候有些和4.3.1不同
public String TransferRestTemplate(String url,String data) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(merchantInfo.getPfx()));
keyStore.load(instream, merchantInfo.getId().toCharArray());
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContextBuilder.create()
.loadKeyMaterial(keyStore, merchantInfo.getId().toCharArray())
.build();
// Allow TLSv1 protocol only
HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"},
null,hostnameVerifier);
CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient);
RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory);
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Connection", "keep-alive");
requestHeaders.add("Accept", "*/*");
requestHeaders.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
requestHeaders.add("Host", "api.mch.weixin.qq.com");
requestHeaders.add("X-Requested-With", "XMLHttpRequest");
requestHeaders.add("Cache-Control", "max-age=0");
requestHeaders.add("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
org.springframework.http.HttpEntity<String> requestEntity =
new org.springframework.http.HttpEntity(new StringEntity(data, "UTF-8"),requestHeaders);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
String sttr = response.getBody();
return sttr;
}
注意:此处HttpEntity 和上面的微信实例的org.apache.http.HttpEntity 是不同的。
这样我们就实现了ssl请求了。
网友评论