背景:

  接到一个需求,客户要求某个模块的rest接口都得通过https访问,客户提供证书。

步骤:

Server端证书生成

  刚开始还没拿到客户的证书,所以通过jdk自带的keytools自己先生成了一个证书用来测试,同事称这个为自签名。

  C:\Program Files\Java\jdk1.8.0_191\jre\bin\keytool.exe 也就是jdk这个自带的程序, 说说怎么用吧。楼主用的windows操作系统

  到JDK的JRE的bin目录下,执行以下命令生成服务端sslServer.p12文件

  keytool -genkey -v -alias sslServer -keyalg RSA -storetype PKCS12 -keystore F:\httpsDemo\sslServer.p12

  注意这个-alias很重要,是证书的别名,后面用得到。sslServer.p12就是生成的自签名证书了,后面需要用客户的证书替换。

  

  看了一些博客的介绍,这个名字和姓氏得是主机的ip,不然会有问题,本着不踩坑的思想,照做就行。当然这里的密码是肯定要记住的。。

Spring配置

将sslServer.p12放在resource目录下,与application.properties同级

# 单向认证开启(客户端校验服务端证书即可)

server.ssl.key-store=classpath:sslServer.p12

server.ssl.key-store-password=server

server.ssl.key-alias=sslServer

server.ssl.keyStoreType=JKS

其中,server.ssl.key-store,server.ssl.key-store-password,server.ssl.key-alias需要根据客户提供的证书进行配置,

server.ssl.key-store对应证书位置,目前是用自生成的签名,部署时需要替换客户证书

server.ssl.key-store-password对应证书密码

server.ssl.key-alias对应生成证书时的证书别名

keyStoreType固定为JKS

到这里为止,服务端做https的认证就已经结束了,很简单吧。可以使用postman测试一波,记得关掉setting里的ssl认证,设置成off

客户端怎么认证

由于楼主的项目是微服架构,本身也会调到这个应用的服务,因此所有调到的地方都得特殊处理下。

https认证分两种,本文只介绍单向认证,即客户端无条件信任服务端的证书,因为我的需求就只要单向

RestTemplate配置

@Configuration

public class RestTemplateConfiguration {

@Value("${readTimeout}")

private String readTimeout;

@Value("${connectionTimeout}")

private String connectionTimeout;

@Bean("restTemplate")

public RestTemplate createRestTemplate() {

ObjectMapper objectMapper = new ObjectMapper();

SimpleModule simpleModule = new SimpleModule();

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

objectMapper.setDateFormat(dateFormat);

objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

simpleModule.addSerializer(Long.class, ToStringSerializer.instance);

simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

objectMapper.registerModule(simpleModule);

RestTemplate restTemplate = new RestTemplate();

restTemplate.setRequestFactory(simpleClientHttpRequestFactory());

List<HttpMessageConverter<?>> converters = new ArrayList<>();

MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();

jsonConverter.setObjectMapper(objectMapper);

converters.add(jsonConverter);

restTemplate.setMessageConverters(converters);

return restTemplate;

}

private ClientHttpRequestFactory simpleClientHttpRequestFactory() {

SslClientHttpRequestFactory factory = new SslClientHttpRequestFactory();

factory.setConnectTimeout(Integer.parseInt(connectionTimeout));

factory.setReadTimeout(Integer.parseInt(readTimeout));

return factory;

}

自定义http请求类

public class SslClientHttpRequestFactory extends SimpleClientHttpRequestFactory {

/**

* 区分https请求

* @param connection

* @param httpMethod

* @throws IOException

*/

@Override

protected void prepareConnection(HttpURLConnection connection, String httpMethod) throws IOException {

if (connection instanceof HttpsURLConnection) {

prepareHttpsConnection((HttpsURLConnection) connection);

}

super.prepareConnection(connection, httpMethod);

}

private void prepareHttpsConnection(HttpsURLConnection connection) {

connection.setHostnameVerifier(new SkipHostnameVerifier());

try {

connection.setSSLSocketFactory(createSslSocketFactory());

}

catch (Exception ex) {

// Ignore

}

}

private SSLSocketFactory createSslSocketFactory() throws Exception {

SSLContext context = SSLContext.getInstance("TLS");

context.init(null, new TrustManager[]{new SkipX509TrustManager()}, new SecureRandom());

return context.getSocketFactory();

}

/**

* 忽略hostName校验,允许ip代替域名

*/

private static class SkipHostnameVerifier implements HostnameVerifier {

@Override

public boolean verify(String s, SSLSession sslSession) {

return true;

}

}

/**

* 信任所有证书

*/

private static class SkipX509TrustManager implements X509TrustManager {

@Override

public X509Certificate[] getAcceptedIssuers() {

return null;

}

@Override

public void checkClientTrusted(X509Certificate[] chain, String authType) {

}

@Override

public void checkServerTrusted(X509Certificate[] chain, String authType) {

}

}

}

然后统一用这个restTemplate去调那个模块的https的服务就ok了,restTemplate怎么调不介绍,基本操作。

.crt和.key导成.p12格式的证书

你以为开发完了?没这么简单。

上面说到我们的证书使用的是自签名证书,但客户提供的证书可能并不是你想的.p12格式的,可能是一个.crt格式的证书加上一个.key格式的私钥。

这时候需要将.crt和.key导成.p12格式的证书。这里就要用到openssl工具了,怎么下载安装不介绍。

执行以下openssl指令导出.p12格式的证书

openssl pkcs12 -export -in test.crt -inkey test.key -passin pass:123456 -password pass:123456 -name server -out server.p12

其中test.crt为客户提供的crt证书
test.key 为客户提供的私钥文件
-passin pass:123456代表给私钥设置密码123456
-password pass:123456 代表给p12文件设置密码123456
-name server 代表导出的证书别名为server
server.p12 为导出的证书文件

则对应的服务器端配置如下
server.ssl.enabled=true
server.ssl.key-store=classpath:server.p12
server.ssl.key-store-password=123456
server.ssl.key-alias=server
server.ssl.key-store-type=JKS

https服务端和客户端的单向认证到此为止。

Rest接口加Https单向认证的更多相关文章

  1. java https单向认证(忽略认证)并支持http基本认证

    https单向认证(忽略认证)并支持http基本认证, 温馨提示 1,jar包要导入对 2,有匿名类编译要注意 3,欢迎提问,拿走不谢!背景知识 Https访问的相关知识中,主要分为单向验证和双向验证 ...

  2. Tomcat添加HTTPS单向认证和双向认证

    前言 前一段时间有了解如何配置Tomcat服务为Https单向认证和双向认证,当时也做了一些记录,今天开始写博客,就把以前的记录拿出来整理下,分享给大家.本文没有介绍证书如何生成,会在下一篇博文里介绍 ...

  3. java实现HTTPS单向认证&TLS指定加密套件

    1.HTTPS介绍 由于HTTP是明文传输,会造成安全隐患,所以在一些特定场景中,必须使用HTTPS协议,简单来说HTTPS=HTTP+SSL/TLS.服务端和客户端的信息传输都是通过TLS进行加密. ...

  4. tomcat 配置https (单向认证)

    1.单向认证,就是传输的数据加密过了,但是不会校验客户端的来源 2.双向认证,如果客户端浏览器没有导入客户端证书,是访问不了web系统的,找不到地址 如果只是加密,单向就行 如果想要用系统的人没有证书 ...

  5. https单向认证和双向认证区别

    关于证书 1.每个人都可以使用一些证书生成工具为自己的站点生成证书(比如jdk的keytool),大家称它为“自签名证书”,但是自己生成的证书是不被互联网承认的,所以浏览器会报安全提示,要求你手动安装 ...

  6. Https单向认证和双向认证介绍

    一.Http HyperText Transfer Protocol,超文本传输协议,是互联网上使用最广泛的一种协议,所有WWW文件必须遵循的标准.HTTP协议传输的数据都是未加密的,也就是明文的,因 ...

  7. 图解 https 单向认证和双向认证!

    来源: 一.Http HyperText Transfer Protocol,超文本传输协议,是互联网上使用最广泛的一种协议,所有WWW文件必须遵循的标准.HTTP协议传输的数据都是未加密的,也就是明 ...

  8. https单向认证和双向认证

    单向认证: .clinet<--server .clinet-->server .client从server处拿到server的证书,通过公司的CA去验证该证书,以确认server是真实的 ...

  9. https 单向认证和双向认证配置

    HTTPS 是我们开发中经常用到的通信加密技术,能有效保护我们网络访问中的安全,本文主要讲解单向 和 双向 https 的配置.关于https 的实现原理在这里我就不赘述了,附上阮一峰老师的关于htt ...

随机推荐

  1. if与switch(break穿透)

    ## if与switch(分支语句) ### 一.if...else if...else1.语法 if(条件表达式1){ 语句体1; }else if(条件表达式2){ 语句体2; }else{ 语句 ...

  2. 零拷贝(Zero-copy) 浅析及其应用

    相信大家都有过面经历,如果跟面试官聊到了操作系统,聊到了文件操作,可能会问你普通的文件读写流程,它有什么缺点,你知道有什么改进的措施.我们经常听说 零拷贝,每次可能只是背诵一些面试要点就过去了,今天我 ...

  3. Maven [ERROR] 不再支持源选项 5,请使用 7 或更高版本的解决办法

    刚刚学Maven,当我点击test时 就出现了这两个错误: [ERROR] 不再支持源选项 5.请使用 7 或更高版本.[ERROR] 不再支持目标选项 5.请使用 7 或更高版本. 后来在看到这篇文 ...

  4. python面试题五:Python 编程

    1.B Tree和B+ Tree的区别? 1.B树中同一键值不会出现多次,并且有可能出现在叶结点,也有可能出现在非叶结点中. 而B+树的键一定会出现在叶结点中,并有可能在非叶结点中重复出现,以维持B+ ...

  5. redis(二十三):Redis 集群(proxy 型)二

    redis的确是一个非常高效的缓存服务器,但是单台redis服务器的内存管理能力有限,如果一味的加大内存的话会导致redis服务器的性能下降,所以就必须要搭建redis集群来提供服务.在redis官方 ...

  6. 01-MySQL支持的数据类型

    1.数值类型 整数类型 MySQL 支持的整数类型有 SQL 标准中的整数类型 INTEGER,SMALLINT,TINYINT.MEDIUMINT和BIGINT.其整数类型的特性如下表所示: 在上述 ...

  7. 网页排名算法PagaRank

    网页排名算法PageRank PageRank,网页排名,又叫做网页级别.是一种利用网页之间的超链接数据进行计算的方法.它是由Google的两位创始人提出的. 对于用户而言,网页排名一般是比较主观的, ...

  8. Spring Boot 2.x基础教程:进程内缓存的使用与Cache注解详解

    随着时间的积累,应用的使用用户不断增加,数据规模也越来越大,往往数据库查询操作会成为影响用户使用体验的瓶颈,此时使用缓存往往是解决这一问题非常好的手段之一.Spring 3开始提供了强大的基于注解的缓 ...

  9. 将python3打包成为exe可执行文件(pyinstaller)

    我们工作中可能会遇到,客户需要一个爬虫或者其他什么功能的python脚本. 这个时候,如果我们直接把我们的python脚本发给客户,会有两个问题: 1.客户的电脑或者服务器可能并没有安装python环 ...

  10. 集训作业 洛谷P1443 马的遍历

    这个题是个搜索,而且有是最少的步数,肯定就是广搜啦,不知道为什么的同学先去学习一下广搜吧. 养成好习惯,看见最少步数就去想想广搜(只是我自己觉得) 竟然这个题可以如此顺畅的想到广搜,感觉不难啊,但还有 ...