java证书验证_java客户端验证https连接(忽略证书验证和证书验证两种方式)

首先根据如下操作生成证书,配置springboot https,生成一个简单的https web服务

验证客户端pom依赖

org.springframework.boot

spring-boot-starter-web

org.apache.httpcomponents

httpclient

4.5.10

org.apache.httpcomponents

httpcore

4.4.12

httpclient和httpcore版本要对应,否则可能会出现异常

验证方式包括跳过证书验证,也即是添加信任,就像浏览器访问自签名https服务时,页面会给出提示“您的链接不是私密连接”,点击了高级,继续前往即是对该服务添加了信任,可以继续访问该网站服务,另外一种方式就是通过服务器证书来验证,下面就直接上代码

跳过证书验证方式

package com.demo.bootdemo;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;

import javax.net.ssl.HttpsURLConnection;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSession;

import javax.net.ssl.TrustManager;

import javax.net.ssl.X509TrustManager;

import org.apache.http.conn.ssl.SSLConnectionSocketFactory;

import org.apache.http.impl.client.HttpClients;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.context.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 = LoggerFactory.getLogger(SkipVerifyRestTemplateBuilder.class);

// 初始化ssl resttemplate

@Bean("skipVerifyRestTemplate")

public RestTemplate skipVerifyRestTemplate() {

RestTemplate rest = new RestTemplate();

SSLConnectionSocketFactory buildSSLSocketFactory = null;

try {

buildSSLSocketFactory = this.buildSSLSocketFactory();

} catch (Exception e) {

logger.error("", 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 = SSLContext.getInstance("SSL");

// 设置信任证书(绕过TrustStore验证)

sslContext.init(null, new TrustManager[] { new AuthX509TrustManager() }, null);

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

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 java.security.cert.CertificateException {

return;

}

public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {

return;

}

}

}

第二种跳过证书验证方式

packagecom.demo.bootdemo;importjava.io.IOException;importjava.security.KeyStore;importjava.security.cert.CertificateException;importjava.security.cert.X509Certificate;importjava.util.ArrayList;importjava.util.List;importjavax.net.ssl.HostnameVerifier;importjavax.net.ssl.HttpsURLConnection;importjavax.net.ssl.SSLContext;importjavax.net.ssl.SSLSession;importorg.apache.http.conn.ssl.SSLConnectionSocketFactory;importorg.apache.http.conn.ssl.TrustStrategy;importorg.apache.http.impl.client.HttpClients;importorg.apache.http.ssl.SSLContexts;importorg.springframework.context.annotation.Bean;importorg.springframework.http.client.HttpComponentsClientHttpRequestFactory;importorg.springframework.stereotype.Component;importorg.springframework.web.client.RestTemplate;

@Componentpublic classSecondSkipVerifyRestTemplateBuilder {

@Bean("secondSkipRestTemplate")publicRestTemplate verifyCaRestTemplate() {

RestTemplate rest= newRestTemplate();

SSLConnectionSocketFactory ssLSocketFactory= null;try{

ssLSocketFactory= sslFactory("PKCS12", "abc123");

}catch(Exception e) {//TODO Auto-generated catch block

e.printStackTrace();

}

HttpComponentsClientHttpRequestFactory httpRequestFactory= newHttpComponentsClientHttpRequestFactory(

HttpClients.custom().setSSLSocketFactory(ssLSocketFactory).build());//设置传递数据超时时长

httpRequestFactory.setReadTimeout(1000);

rest.setRequestFactory(httpRequestFactory);//如果返回的数据非json则可能需要添加对应httpmessageconverter//Jaxb2RootElementHttpMessageConverter converter = new//Jaxb2RootElementHttpMessageConverter();//

//List mediaTypeList = new ArrayList<>();//mediaTypeList.addAll(converter.getSupportedMediaTypes());//mediaTypeList.add(MediaType.TEXT_HTML);//converter.setSupportedMediaTypes(mediaTypeList);//

//List> list = new ArrayList<>();//list.add(converter);//rest.setMessageConverters(list);

returnrest;

}publicSSLConnectionSocketFactory sslFactory(String keyStoreType, String keyPassword) {

SSLConnectionSocketFactory sslConnectionSocketFactory= null;try{

SSLContext sslcontext=SSLContexts.custom()// //忽略掉对服务器端证书的校验

.loadTrustMaterial(newTrustStrategy() {

@Overridepublic boolean isTrusted(X509Certificate[] chain, String authType) throwsCertificateException {return true;

}

}).build();

sslConnectionSocketFactory= new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null,

SSLConnectionSocketFactory.getDefaultHostnameVerifier());

}catch(Exception e) {

e.printStackTrace();

}returnsslConnectionSocketFactory;

}

}

根据证书验证

packagecom.demo.bootdemo;importjava.io.IOException;importjava.security.KeyStore;importjava.util.ArrayList;importjava.util.List;importjavax.net.ssl.HostnameVerifier;importjavax.net.ssl.SSLContext;importjavax.net.ssl.SSLSession;importorg.apache.http.conn.ssl.SSLConnectionSocketFactory;importorg.apache.http.conn.ssl.TrustSelfSignedStrategy;importorg.apache.http.impl.client.HttpClients;importorg.apache.http.ssl.SSLContexts;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.core.io.Resource;importorg.springframework.http.client.HttpComponentsClientHttpRequestFactory;importorg.springframework.stereotype.Component;importorg.springframework.web.client.RestTemplate;

@Componentpublic classVerifyCaRestTemplateBuilder {private Logger logger = LoggerFactory.getLogger(VerifyCaRestTemplateBuilder.class);

@Value("classpath:cert.p12")privateResource certFile;

@Bean("verifyCaRestTemplate")publicRestTemplate verifyCaRestTemplate() {

RestTemplate rest= newRestTemplate();

SSLConnectionSocketFactory ssLSocketFactory= null;try{

ssLSocketFactory= sslFactory("PKCS12", "abc123");

}catch(Exception e) {

logger.error("", e);

}

HttpComponentsClientHttpRequestFactory httpRequestFactory= newHttpComponentsClientHttpRequestFactory(

HttpClients.custom().setSSLSocketFactory(ssLSocketFactory).build());//设置传递数据超时时长

httpRequestFactory.setReadTimeout(1000);

rest.setRequestFactory(httpRequestFactory);//如果返回的数据非json则可能需要添加对应httpmessageconverter//Jaxb2RootElementHttpMessageConverter converter = new//Jaxb2RootElementHttpMessageConverter();//

//List mediaTypeList = new ArrayList<>();//mediaTypeList.addAll(converter.getSupportedMediaTypes());//mediaTypeList.add(MediaType.TEXT_HTML);//converter.setSupportedMediaTypes(mediaTypeList);//

//List> list = new ArrayList<>();//list.add(converter);//rest.setMessageConverters(list);

returnrest;

}publicSSLConnectionSocketFactory sslFactory(String keyStoreType, String keyPassword) {

SSLConnectionSocketFactory sslConnectionSocketFactory= null;try{

KeyStore keyStore= null;try{

keyStore=KeyStore.getInstance(keyStoreType);

keyStore.load(certFile.getInputStream(), keyPassword.toCharArray());

}catch(IOException e) {

logger.error("", e);

}

HostnameVerifier hv= newHostnameVerifier() {

@Overridepublic booleanverify(String urlHostName, SSLSession session) {//如果需要验证https域名,可以在该处做判断,如果访问的hostname与判断不一致,则会出现如下异常//if("localhost".equals(urlHostName)) {//return true;//}else {//return false;//}//此处不校验hostname,接收所有hostname,只是用于测试。

return true;

}

};

SSLContext sslcontext=SSLContexts.custom()

.loadTrustMaterial(certFile.getFile(), keyPassword.toCharArray(),newTrustSelfSignedStrategy())

.loadKeyMaterial(keyStore, keyPassword.toCharArray()).build();

sslConnectionSocketFactory= new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, hv);

}catch(Exception e) {

e.printStackTrace();

}returnsslConnectionSocketFactory;

}

}

注:在上述HostnameVerifier 中,可以验证hostname有效性,如果无效,返回fase,则会出现类似以下异常

javax.net.ssl.SSLPeerUnverifiedException: Certificate for doesn't match any of the subject alternative names: []

测试controller

packagecom.demo.bootdemo;importjavax.annotation.Resource;importorg.springframework.http.ResponseEntity;importorg.springframework.stereotype.Controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.ResponseBody;importorg.springframework.web.client.RestTemplate;

@Controllerpublic classHttpsSendController {

@Resource(name= "skipVerifyRestTemplate")privateRestTemplate skipVerifyRestTemplate;

@Resource(name= "verifyCaRestTemplate")privateRestTemplate verifyCaRestTemplate;

@Resource(name= "secondSkipRestTemplate")privateRestTemplate secondSkipRestTemplate;

@RequestMapping("/skip")

@ResponseBodypublicString skipVerifyCert() {

ResponseEntity forEntity = skipVerifyRestTemplate.getForEntity("https://127.0.0.1:8443/test",

String.class, newObject[] {});returnforEntity.getBody();

}

@RequestMapping("/secondskip")

@ResponseBodypublicString secondSkipVerifyCert() {

ResponseEntity forEntity = skipVerifyRestTemplate.getForEntity("https://127.0.0.1:8443/test",

String.class, newObject[] {});returnforEntity.getBody();

}

@RequestMapping("/verify")

@ResponseBodypublicString verifyCert() {

ResponseEntity forEntity = verifyCaRestTemplate.getForEntity("https://127.0.0.1:8443/test",

String.class, newObject[] {});returnforEntity.getBody();

}

}

可分别访问当前客户端的skip、secondskip、verify验证结果


版权声明:本文为weixin_34352633原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。