java客户端验证https连接(忽略证书验证和证书验证两种⽅
式)
⾸先根据如下操作⽣成证书,配置springboot https,⽣成⼀个简单的https web服务
验证客户端pom依赖
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.10</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpcore</artifactId>
<version>4.4.12</version>
</dependency>
httpclient和httpcore版本要对应,否则可能会出现异常
验证⽅式包括跳过证书验证,也即是添加信任,就像浏览器访问⾃签名https服务时,页⾯会给出提⽰“您的链接不是私密连接”,点击了⾼级,继续前往即是对该服务添加了信任,可以继续访问该⽹站服务,另外⼀种⽅式就是通过服务器证书来验证,下⾯就直接上代码
springframework依赖跳过证书验证⽅式
package com.demo.bootdemo;
import CertificateException;
import X509Certificate;
import javax.ssl.HostnameVerifier;
import javax.ssl.HttpsURLConnection;
import javax.ssl.SSLContext;
import javax.ssl.SSLSession;
import javax.ssl.TrustManager;
import javax.ssl.X509TrustManager;
import org.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import t.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class SkipVerifyRestTemplateBuilder {
private Logger logger = Logger(SkipVerifyRestTemplateBuilder.class);
// 初始化ssl resttemplate
@Bean("skipVerifyRestTemplate")
public RestTemplate skipVerifyRestTemplate() {
RestTemplate rest = new RestTemplate();
SSLConnectionSocketFactory buildSSLSocketFactory = null;
try {
buildSSLSocketFactory = this.buildSSLSocketFactory();
} catch (Exception e) {
<("", e);
}
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(
HttpClients.custom().setSSLSocketFactory(buildSSLSocketFactory).build());
factory.setConnectionRequestTimeout(1000);
factory.setConnectTimeout(1000);
rest.setRequestFactory(factory);
return rest;
}
private SSLConnectionSocketFactory buildSSLSocketFactory() throws Exception {
SSLContext sslContext = Instance("SSL");
// 设置信任证书(绕过TrustStore验证)
sslContext.init(null, new TrustManager[] { new AuthX509TrustManager() }, null);
HttpsURLConnection.SocketFactory());
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
new String[] { "TLSv1" }, null, new HostnameVerifier() {
// hostname,默认返回true,不验证hostname
@Override
public boolean verify(String urlHostName, SSLSession session) {
return true;
}
});
return sslConnectionSocketFactory;
}
private class AuthX509TrustManager implements TrustManager, X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkServerTrusted(X509Certificate[] certs, String authType)
throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
}
第⼆种跳过证书验证⽅式
package com.demo.bootdemo;
import java.io.IOException;
import java.security.KeyStore;
import CertificateException;
import X509Certificate;
import java.util.ArrayList;
import java.util.List;
import javax.ssl.HostnameVerifier;
import javax.ssl.HttpsURLConnection;
import javax.ssl.SSLContext;
import javax.ssl.SSLSession;
import org.ssl.SSLConnectionSocketFactory;
import org.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import t.annotation.Bean;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class SecondSkipVerifyRestTemplateBuilder {
@Bean("secondSkipRestTemplate")
public RestTemplate verifyCaRestTemplate() {
RestTemplate rest = new RestTemplate();
SSLConnectionSocketFactory ssLSocketFactory = null;
try {
ssLSocketFactory = sslFactory("PKCS12", "abc123");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpReq
uestFactory( HttpClients.custom().setSSLSocketFactory(ssLSocketFactory).build());
// 设置传递数据超时时长
httpRequestFactory.setReadTimeout(1000);
rest.setRequestFactory(httpRequestFactory);
// 如果返回的数据⾮json则可能需要添加对应httpmessageconverter
// Jaxb2RootElementHttpMessageConverter converter = new
// Jaxb2RootElementHttpMessageConverter();
//
// List<MediaType> mediaTypeList = new ArrayList<>();
// mediaTypeList.SupportedMediaTypes());
// mediaTypeList.add(MediaType.TEXT_HTML);
/
/ converter.setSupportedMediaTypes(mediaTypeList);
//
// List<HttpMessageConverter<?>> list = new ArrayList<>();
// list.add(converter);
// rest.setMessageConverters(list);
return rest;
}
public SSLConnectionSocketFactory sslFactory(String keyStoreType, String keyPassword) {
SSLConnectionSocketFactory sslConnectionSocketFactory = null;
try {
SSLContext sslcontext = SSLContexts.custom()
/
///忽略掉对服务器端证书的校验
.loadTrustMaterial(new TrustStrategy() {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, DefaultHostnameVerifier());
} catch (Exception e) {
e.printStackTrace();
}
return sslConnectionSocketFactory;
}
}
根据证书验证
package com.demo.bootdemo;
import java.io.IOException;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;
import javax.ssl.HostnameVerifier;
import javax.ssl.SSLContext;
import javax.ssl.SSLSession;
import org.ssl.SSLConnectionSocketFactory;
import org.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import t.annotation.Bean;
import io.Resource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class VerifyCaRestTemplateBuilder {
private Logger logger = Logger(VerifyCaRestTemplateBuilder.class);
@Value("classpath:cert.p12")
private Resource certFile;
@Bean("verifyCaRestTemplate")
public RestTemplate verifyCaRestTemplate() {
RestTemplate rest = new RestTemplate();
SSLConnectionSocketFactory ssLSocketFactory = null;
try {
ssLSocketFactory = sslFactory("PKCS12", "abc123");
} catch (Exception e) {
<("", e);
}
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory( HttpClients.custom().setSSLSocketFactory(ssLSocketFactory).build());
// 设置传递数据超时时长
httpRequestFactory.setReadTimeout(1000);
rest.setRequestFactory(httpRequestFactory);
// 如果返回的数据⾮json则可能需要添加对应httpmessageconverter
// Jaxb2RootElementHttpMessageConverter converter = new
// Jaxb2RootElementHttpMessageConverter();
//
// List<MediaType> mediaTypeList = new ArrayList<>();
// mediaTypeList.SupportedMediaTypes());
// mediaTypeList.add(MediaType.TEXT_HTML);
// converter.setSupportedMediaTypes(mediaTypeList);
//
// List<HttpMessageConverter<?>> list = new ArrayList<>();
// list.add(converter);
// rest.setMessageConverters(list);
return rest;
}
public SSLConnectionSocketFactory sslFactory(String keyStoreType, String keyPassword) {
SSLConnectionSocketFactory sslConnectionSocketFactory = null;
try {
KeyStore keyStore = null;
try {
keyStore = Instance(keyStoreType);
keyStore.InputStream(), CharArray());
} catch (IOException e) {
<("", e);
}
HostnameVerifier hv = new HostnameVerifier() {
@Override
public boolean verify(String urlHostName, SSLSession session) {
// 如果需要验证https域名,可以在该处做判断,如果访问的hostname与判断不⼀致,则会出现如下异常
// if("localhost".equals(urlHostName)) {
// return true;
// }else {
// return false;
// }
// 此处不校验hostname,接收所有hostname,只是⽤于测试。
return true;
}
};
SSLContext sslcontext = SSLContexts.custom()
.File(), CharArray(), new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, CharArray()).build();
sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, hv);
} catch (Exception e) {
e.printStackTrace();
}
return sslConnectionSocketFactory;
}
}
注:在上述HostnameVerifier 中,可以验证hostname有效性,如果⽆效,返回fase,则会出现类似以下异常
javax.ssl.SSLPeerUnverifiedException: Certificate for <localhost> doesn't match any of the subject alternative names: []测试controller
package com.demo.bootdemo;
import javax.annotation.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
@Controller
public class HttpsSendController {
@Resource(name = "skipVerifyRestTemplate")
private RestTemplate skipVerifyRestTemplate;
@Resource(name = "verifyCaRestTemplate")
private RestTemplate verifyCaRestTemplate;
@Resource(name = "secondSkipRestTemplate")
private RestTemplate secondSkipRestTemplate;
@RequestMapping("/skip")
@ResponseBody
public String skipVerifyCert() {
ResponseEntity<String> forEntity = ForEntity("127.0.0.1:8443/test", String.class, new Object[] {});
Body();
}
@RequestMapping("/secondskip")
@ResponseBody
public String secondSkipVerifyCert() {
ResponseEntity<String> forEntity = ForEntity("127.0.0.1:8443/test", String.class, new Object[] {});
Body();
}
@RequestMapping("/verify")
@ResponseBody
public String verifyCert() {
ResponseEntity<String> forEntity = ForEntity("127.0.0.1:8443/test", String.class, new Object[] {});
Body();
}
}
可分别访问当前客户端的skip、secondskip、verify验证结果
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论