java客户端验证https连接(忽略证书验证和证书验证两种方式)
首先根据如下操作生成证书,配置springboot https,生成一个简单的https web服务
https://www.cnblogs.com/qq931399960/p/11889349.html
验证客户端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服务时,页面会给出提示“您的链接不是私密连接”,点击了高级,继续前往即是对该服务添加了信任,可以继续访问该网站服务,另外一种方式就是通过服务器证书来验证,下面就直接上代码
跳过证书验证方式
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;
}
}
}
第二种跳过证书验证方式
package com.demo.bootdemo; import java.io.IOException;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession; import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
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 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 HttpComponentsClientHttpRequestFactory(
HttpClients.custom().setSSLSocketFactory(ssLSocketFactory).build());
// 设置传递数据超时时长
httpRequestFactory.setReadTimeout(1000); rest.setRequestFactory(httpRequestFactory); // 如果返回的数据非json则可能需要添加对应httpmessageconverter
// Jaxb2RootElementHttpMessageConverter converter = new
// Jaxb2RootElementHttpMessageConverter();
//
// List<MediaType> mediaTypeList = new ArrayList<>();
// mediaTypeList.addAll(converter.getSupportedMediaTypes());
// 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,
SSLConnectionSocketFactory.getDefaultHostnameVerifier());
} 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.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession; import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.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 org.springframework.context.annotation.Bean;
import org.springframework.core.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 = LoggerFactory.getLogger(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) {
logger.error("", 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.addAll(converter.getSupportedMediaTypes());
// 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 = KeyStore.getInstance(keyStoreType);
keyStore.load(certFile.getInputStream(), keyPassword.toCharArray());
} catch (IOException e) {
logger.error("", 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()
.loadTrustMaterial(certFile.getFile(), keyPassword.toCharArray(), new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, keyPassword.toCharArray()).build();
sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1" }, null, hv); } catch (Exception e) {
e.printStackTrace();
}
return sslConnectionSocketFactory;
} }
注:在上述HostnameVerifier 中,可以验证hostname有效性,如果无效,返回fase,则会出现类似以下异常
javax.net.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 = skipVerifyRestTemplate.getForEntity("https://127.0.0.1:8443/test",
String.class, new Object[] {});
return forEntity.getBody();
} @RequestMapping("/secondskip")
@ResponseBody
public String secondSkipVerifyCert() {
ResponseEntity<String> forEntity = skipVerifyRestTemplate.getForEntity("https://127.0.0.1:8443/test",
String.class, new Object[] {});
return forEntity.getBody();
} @RequestMapping("/verify")
@ResponseBody
public String verifyCert() {
ResponseEntity<String> forEntity = verifyCaRestTemplate.getForEntity("https://127.0.0.1:8443/test",
String.class, new Object[] {});
return forEntity.getBody();
} }
可分别访问当前客户端的skip、secondskip、verify验证结果
java客户端验证https连接(忽略证书验证和证书验证两种方式)的更多相关文章
- Java通过图片url地址获取图片base64位字符串的两种方式
工作中遇到通过图片的url获取图片base64位的需求.一开始是用网上的方法,通过工具类Toolkit,虽然实现的代码比较简短,不过偶尔会遇到图片转成base64位不正确的情况,至今不知道为啥. 之后 ...
- Java并发基础01. 传统线程技术中创建线程的两种方式
传统的线程技术中有两种创建线程的方式:一是继承Thread类,并重写run()方法:二是实现Runnable接口,覆盖接口中的run()方法,并把Runnable接口的实现扔给Thread.这两种方式 ...
- windows/tomcat 修改java虚拟机JVM以utf-8字符集加载class文件的两种方式
1.情景展示 做了这么长时间的java开发,但是,你知道JVM是以怎样的编码加载.解析class文件的吗? 我们知道,通常情况下,我们会将java文件的字符集修改成utf-8,这样,理所当然地就认 ...
- 基于Java使用Flink读取CSV文件,针对批处理,多表联合两种方式Table类和Join方法的实现数据处理,再入CSV文件
Maven依赖 源头 <dependencies> <dependency> <groupId>org.projectlombok</groupId> ...
- Java 爬虫遇上数据异步加载,试试这两种办法!
这是 Java 爬虫系列博文的第三篇,在上一篇 Java 爬虫遇到需要登录的网站,该怎么办? 中,我们简单的讲解了爬虫时遇到登录问题的解决办法,在这篇文章中我们一起来聊一聊爬虫时遇到数据异步加载的问题 ...
- 第二节:SSL证书的申请、配置(IIS通用)及跳转Https请求的两种方式
一. 相关概念介绍 1. SSL证书服务 SSL证书服务由"服务商"联合多家国内外数字证书管理和颁发的权威机构.在xx云平台上直接提供的服务器数字证书.您可以在阿里云.腾讯云等平台 ...
- Java连接Neo4j的两种方式
1.Neo4j数据库的两种方式 Neo4j可以以两种方式运行: Java应用程序中的嵌入式数据库 通过REST的独立服务器 不管哪一种方式,这个选择不会影响查询和使用数据库的方式. 它是由应用程序的性 ...
- 并发编程 ~~~ 多进程~~~进程创建的两种方式, 进程pid, 验证进程之间的空间隔离, 进程对象join方法, 进程对象其他属性
一 进程创建的两种方式 from multiprocessing import Process import time def task(name): print(f'{name} is runnin ...
- JAVA发送http GET/POST请求的两种方式+JAVA http 请求手动配置代理
java发送http get请求,有两种方式. 第一种用URLConnection: public static String get(String url) throws IOException { ...
- 两种方式实现java生成Excel
Web应用中难免会遇到需要将数据导出并生成excel文件的需求.同样,对于本博客中的总结,也是建立在为了完成这样的一个需求,才开始去了解其实现形式,并且顺利完成需求的开发,先将实现过程总结于此.本博文 ...
随机推荐
- 3 webpack 4 加vue 2.0生产环境搭建
1 在前两篇笔记中已经能把开发环境弄好了,接来下构建他的生产环境 2 使用npm 安装url-loader和file-loader来支持图片和字体 npm install --save-dev url ...
- 怎么读取properties文件和ini文件?
一.读取properties文件: properties中的内容: server.ip = 127.0.0.1 server.port = 22 //原生java即可读取public static v ...
- 跟着minium官网介绍学习minium-----(一)
某天,再打开微信开发者工具的时候收到一条推送.说是微信小程序自动化框架 Python 版 -- Minium 公测. Url如下: https://developers.weixin.qq.com/c ...
- Vue 循环 [Vue warn]: Avoid using non-primitive value as key
页面中不添加 :key 索引的时候,会不停的提示虚线,但不影响使用 后来加了一个索引,加成了:key= "content" 从后台取出来的contents是一个list,里面有多 ...
- 面对runc逃逸漏洞,华为云容器为您保驾护航
背景信息 基于runc运行时的容器存在安全漏洞,攻击者可以通过恶意容器镜像等方式获取宿主机root执行权限.漏洞CVE-2019-5736的详细信息,请参见 https://cve.mitre.org ...
- H5之postMessage
对于跨域我们有很多的解决方案,今天我来分享一下postMessage的那点事,postMessage是html5新增的一个解决跨域的一个方法,不过很可惜万恶的ie6,7不支持 postMessage( ...
- 洛谷P5002 专心OI - 找祖先
题目概括 题目描述 这个游戏会给出你一棵树,这棵树有\(N\)个节点,根结点是\(R\),系统会选中\(M\)个点\(P_1,P_2...P_M\). 要Imakf回答有多少组点对\((u_i,v_i ...
- 解决 分布式事务中HRESULT:0x8004D025 错误
最近在开发分布式事务的过程中,碰到 该伙伴事务管理器已经禁止了它对远程/网络事务的支持. (异常来自 HRESULT:0x8004D025)的错误. 后来检查到,原来是数据库服务器的MSDTC 没有设 ...
- ubuntu 18.04 enp8s0更改网口名称为eth0
尝试各种方法均不成功,后参考如下方法终于成功: 方法一:单纯改网卡名,重启后显示原网卡名. 如我的网卡名是enp8s0 >> ip link set enp8s0 down //关闭网卡 ...
- MySQL内存结构
实际上MySQL内存的组成和Oracle类似,也可以分为SGA(系统全局区)和PGA(程序缓存区). mysql>show variables like "%buffer%" ...