1、HTTPS介绍

由于HTTP是明文传输,会造成安全隐患,所以在一些特定场景中,必须使用HTTPS协议,简单来说HTTPS=HTTP+SSL/TLS。服务端和客户端的信息传输都是通过TLS进行加密。这样就能在一定程度上避免敏感信息被截取。

在通信过程中,请求方称为客户端,响应方称为服务端。HTTPS请求流程如图:

1、客户端向服务端发送加密版本、加密算法种类、随机数信息等。

2、服务端返回客户端发送的信息并带上服务端证书(公钥证书)。

3、客户端效验服务端证书的合法性。

4、验证不通过终止通信,验证通过继续通信,客户端将自己所支持的所有加密算法全部发送给服务端供服务端进行选择。

5、服务端在客户端发送的加密算法中选择加密程度最高的机密方式。

6、服务端将选择的加密算法通过明文返回给客户端。

7、客户端收到服务端返回的加密方式后,使用该加密方式生成随机码(用作后续通信过程中加密的秘钥),使用服务端返回的公钥加密后发送至服务端。

8、服务端收到信息后,使用自己的私钥进行解密,获取加密秘钥。

在之后的通信中,客户端和服务端都将采用该秘钥进行加密。

2、自签证书的生成

生成证书和转换证书格式需要密码,秘密建议全部设置一致的。

2.1 生成根证书

# 生成root私钥

openssl genrsa -out root.key 1024

# 根据私钥创建根证书请求文件,需要输入一些证书的元信息:邮箱、域名、密码等

openssl req -new -out root.csr -key root.key

# 结合私钥和请求文件,创建根证书,有效期10年

openssl x509 -req -in root.csr -out root.crt -signkey root.key -CAcreateserial -days 3650

2.2 生成服务端证书

# 创建服务端私钥

openssl genrsa -out server.key 1024

# 根据私钥生成请求文件需要证书元信息:邮箱、域名、密码等

openssl req -new -out server.csr -key server.key

# 结合私钥和请求文件创建服务端证书,有效期10年

openssl x509 -req -in server.csr -out server.crt -signkey server.key -CA root.crt -CAkey root.key -CAcreateserial -days 3650

单向认证不需要生成客户端证书,所以做单向认证的证书到此就完成了。但是为了之后的测试方便(java中作为服务端使用.p12/.jks类型比较方便,作为客户端使用.p12/.jks比较方便),将生成的证书进一步转换。

2.3 证书类型转换

# 根证书crt转p12需要密码

openssl pkcs12 -export -in root.crt -inkey root.key -out root.p12

# 服务端证书crt转p12需要密码

openssl pkcs12 -export -in server.crt -inkey server.key -out server.p12

# p12转jks需要密码(实际项目中可以不用,仅做测试)

keytool -importkeystore -srckeystore root.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore root.jks

生成的全部文件如下:

使用java实现:服务端需要server.p12文件,客户端需要root.p12文件。可以有其他不同的实现方式,需要不同类型的文件可以通过openssl或者keytool进行证书格式转化。(jks格式只是用来测试实际项目中可以不生成)。

3、自签证书的使用

3.1 服务端配置

1、证书放到resources目录下(其他目录也可以,配置文件中写好对应路径就行)

2、在application中添加配置

# 新增http端口

server.port=8075

# 证书路径resource下

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

# 密码

server.ssl.key-store-password=hcm@123++

# 服务端限定加密算法

server.ssl.ciphers=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384

# 服务端限定TLS版本

server.ssl.protocol=TLSv1.2

根据实际项目中,客户端和服务端都限定使用这两种算法。

3、配置之后启动项目,之前的端口就是https端口了,这样就不能使用http访问了,需要使用以下代码同时支持http。

//配置http

@Bean

public ServletWebServerFactory servletContainer() {

TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();

tomcat.addAdditionalTomcatConnectors(createStandardConnector());

return tomcat;

}

private Connector createStandardConnector() {

Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");

connector.setPort(“需要使用的http端口”);

return connector;

}

启动项目出现一个http端口一个https端口就是端口开启成功了

可以写个测试方法测试一下

可以看出http和https均可以访问,至此服务端配置完成并且测试通过。

3.2 客户端配置

客户端配置有两种方案,其一是把根证书导入到jdk中,其二就是本次使用的代码实现。

由于不太了解导入到jdk是不是有隐患,所有对第一种方案并没有深入研究,简单的导入命令如下

# 添加cacerts:

keytool -import -v -trustcacerts -alias 1 -file "C:\Users\zhouyinhang\Desktop\fsdownload\testca1\root.crt" -keystore "G:\Program Files\java\jdk1.8.0_181\jre\lib\security\cacerts"

# 查看cacerts中的证书列表:

keytool -list -keystore "C:\Program Files\Java\jre1.8.0_181\lib\security\cacerts" -storepass changeit

# 删除cacerts中指定名称的证书:

keytool -delete -alias 1 -keystore "G:\Program Files\java\jdk1.8.0_181\jre\lib\security\cacerts" -storepass changeit

其中-alias 1 “1”为别名可以通过命令keytool -list -v -keystore root.p12查看,需要注意的是导入jdk的证书格式不可以是p12或者jks格式,可以使用最先生成的crt格式。

下面主要介绍第二种通过代码实现客户端根证书的使用。

通过代码实现主要构造httpClient类

httpClient类作用就是通过记载根证书、密码、配置TLS版本、配置支持的加密套件、配置是否域名效验返回一个CloseableHttpClient连接对象,使用该对象可以直接请求https服务端接口,也可以对CloseableHttpClient对象封装成ReatTemplate。具体实现可以参考源码

下面代码是核心代码,包括如何建立SSLContext连接,TrustManager如何创建。

其中初始化SSLContext是传入三个参数分别是keyManagers(授权的秘钥管理器,用来验证授权),trustManagers(被授权的证书管理器,用来验证服务端证书),secureRandom(随机数,可以填null,SSLContext内部有实现)。项目中cac组件作为客户端时,而且是单向认证所以只需要传第二个参数即可。

public static CloseableHttpClient initSSLConfig() throws Exception {

//证书类型

KeyStore keyStore = KeyStore.getInstance("PKCS12");

//加载根证书

keyStore.load(new FileInputStream(PATH),PASSWORD.toCharArray());

// 创建信任库管理工厂实例

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");

// 初始化信任库

trustManagerFactory.init(keyStore);

TrustManager[] tm = trustManagerFactory.getTrustManagers();

// 建立TLS连接

SSLContext sc = SSLContext.getInstance("TLSv1.2");

         // 初始化SSLContext

sc.init(null,  tm, null);

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(

sc,

// 指定TLS版本

new String[]{"TLSv1.2"},

// 指定算法

new String[]{"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},

// 取消域名验证

new HostnameVerifier(){

@Override

public boolean verify(String string, SSLSession ssls) {

return true;

}

}

);

CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

return httpClient;

}

使用同一套证书测试结果

测试不同证书时候,有两种选择,其一把其他根证书签发的服务端证书放到请求的服务器上。其二客户端使用其他的根证书。(根证书和服务器证书不匹配)

错误信息如图

由此可以看出客户端已经使用根证书效验服务端返回的证书了。

demo只是作为测试使用,具体使用要结合实际项目。例如cac组件中基线没有用restTemplate,如果使用restTemplate的话改动太大,只能使用client直接发起请求的方式。

4、正确使用HTTPS

虽然在通信中有必要使用HTTPS,但是不能全部通信都使用,原因主要有两点:

  • HTTPS需要认证,所以相对于HTTP来说效率肯定是比较慢的。
  • 要进行HTTPS通信,必须要有证书,这些证书一般都需要向认证机构购买。

java实现HTTPS单向认证&TLS指定加密套件的更多相关文章

  1. JAVA实现https单向认证

    //关于http 须要两个jar包 httpclient-4.0.jar httpcore-4.0.1.jar private static final HttpClient httpClient = ...

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

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

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

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

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

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

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

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

  6. Rest接口加Https单向认证

    背景: 接到一个需求,客户要求某个模块的rest接口都得通过https访问,客户提供证书. 步骤: Server端证书生成 刚开始还没拿到客户的证书,所以通过jdk自带的keytools自己先生成了一 ...

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

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

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

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

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

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

随机推荐

  1. 【stm32】基于hal库使用野火指南者esp8266 WIFI模块进行TCP传输

    UART.c #include "stm32f1xx_it.h" #include "LED.h" #include "UART.h" #i ...

  2. Salesforce LWC学习(三十八) lwc下如何更新超过1万的数据

    背景: 今天项目组小伙伴问了一个问题,如果更新数据超过1万条的情况下,有什么好的方式来实现呢?我们都知道一个transaction只能做10000条DML数据操作,那客户的操作的数据就是超过10000 ...

  3. Latex 入门教程

    Latex 入门教程 学习途径:LaTex入门_哔哩哔哩_bilibili 运行环境:texlive2021.texstudio-4.1.2-win-qt6 1. 基本结构 整个 Latex 文件分为 ...

  4. 【HTML基础习题】HTML5+CSS3做问卷星登录页面

    源代码下载地址:https://download.csdn.net/download/weixin_44893902/12839539 码云仓库地址: https://gitee.com/ynavc/ ...

  5. Windows下安装配置Maven

    1.下载Maven 官方下载地址:http://maven.apache.org/download.cgi 目前Apache Maven最小版本为3.6.3, 下载适合Windows的安装包apach ...

  6. 为什么要避免在 Go 中使用 ioutil.ReadAll?

    原文链接: 为什么要避免在 Go 中使用 ioutil.ReadAll? ioutil.ReadAll 主要的作用是从一个 io.Reader 中读取所有数据,直到结尾. 在 GitHub 上搜索 i ...

  7. 简单通俗讲解 android 内存泄漏

    在柠檬班社区看到老师一篇android 内存泄漏写的通俗易懂,绝对是小白能看懂的! 原文:http://www.lemfix.com/topics/2 平常会听到程序员说"内存泄漏" ...

  8. JMeter_csv文件参数化

    CSV Data Set Config 可以从指定的文件中一行一行的提取文本内容,每行的数据通过分隔符拆解,并与变量名一一对应,就可以供取样器引用了. 所以在配置数据时,我们需要把参数化的数据进行分行 ...

  9. springMVC+redis+redis自定义工具类 的配置

    1. maven项目,加入这一个依赖包即可, <dependency> <groupId>redis.clients</groupId> <artifactI ...

  10. java 方法 compareTo()的正确使用

    总结:(1)如果比较的是数字 则结果大于则为1 等于则为0 小于则为-1(2)如果比较的是字符[串] 则按照从左到右排序找对应不一样的字符第一个字符, 然后将字符装对应的ASCLL码数字,做减法运算, ...