背景:

  接到一个需求,客户要求某个模块的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. __stdcall、__cdcel和__fastcall三者的区别

    转自:https://www.cnblogs.com/huhewei/p/6080143.html 一.概述 __stdcall.__cdecl和__fastcall是三种函数调用协议,函数调用协议会 ...

  2. python positional argument follows keyword argument

    关键字参数必须跟随在位置参数后面! 因为python函数在解析参数时, 是按照顺序来的, 位置参数是必须先满足, 才能考虑其他可变参数.

  3. python 追踪函数调用

    from flask import Flask import traceback app = Flask(__name__) @app.route('/') def hello_world(): tr ...

  4. Elasticsearch备份数据

    Elasticsearch备份数据 1.建立备份目录 POST _snapshot/my_backup/ { "type": "fs", "setti ...

  5. Unity-内存

    editor 和runtime的内存管理分开的 unity检测不到native内存容量 如c++,lua 一个asset一个ab的问题在于 每个asset都有对应的文件头,并不划算 IL2CPP抛弃了 ...

  6. 《Head First 设计模式》:装饰者模式

    正文 一.定义 装饰者模式动态地将责任(功能)附加到对象上.若要扩展功能,装饰者提供了比继承更有弹性的替代方案. 要点: 装饰者和被装饰者有相同的超类型. 可以用一个或多个装饰者包装一个对象. 既然装 ...

  7. C#生成Excel文档(EPPlus)

    1.公式计算 worksheet.Cells["D2:D5"].Formula = "B2*C2";//这是乘法的公式,意思是第二列乘以第三列的值赋值给第四列, ...

  8. JavaScript定时器及回调用法

    JavaScript定时器及回调用法 循环定时任务 // 假设现在有这样一个需求:我需要请求一个接口,根据返回结果判断需不需要重复请求,直到达到某一条件为止,停止请求执行某操作 <script ...

  9. Ethical Hacking - NETWORK PENETRATION TESTING(9)

    WEP Cracking Packet Injection What if the AP was idle, or had no clients associated with it? In this ...

  10. CUDA Programming Guide 学习笔记

    CUDA学习笔记 GPU架构 GPU围绕流式多处理器(SM)的可扩展阵列搭建,每个GPU有多个SM,每个SM支持数百个线程并发执行.目前Nvidia推出了6种GPU架构(按时间顺序,详见下图):Fer ...