SSL证书
你好呀,我的老朋友!我是老寇,欢迎来到老寇云平台!
几天不见啦,我又来啦!
# 什么是SSL?
SSL全称为 Security Socket Layer(安全套接字层),它是一种加密安全协议。 它的诞生就是 为了确保 Internet通信中的隐私、身份验证和数据完整性。 SSL是TLS加密的前身。(现在使用的是TLS)
# 什么是TLS?
TLS全称为 Transport Layer Security(安全传输层),它也是一种加密安全协议, 可以为互联网通信提供私密性和数据完整性。实施TLS是构建安全web应用的一个标准实践。
# 为什么企业和web应用程序应该使用TLS协议?
TLS加密可以帮助web应用程序免受数据泄露和其他攻击,如今,受TLS保护的HTTPS是网站的标准做法。 (知识点补充:2018年发布的TLS1.3进一步提高了TLS的速度。TLS1.3中的TLS握手仅一次往返<即来回通信> 而不是以前的两次,将握手过程所需时间缩短了几毫秒。如果用户以前已连接过网站,TLS握手往返次数为0, 从而进一步加快了速度。)
# SSL/TLS如何工作?
- 为了提高高度隐私,SSL会对通过Web传输的数据进行加密,这意味着,任何试图截取此数据的人都只会看到几乎无法解密的乱码字符。
- SSL在两个通道设备之间启动称为握手的身份验证过程,以确保两个设备确实是它们所声称的真实身份。
- SSL还对数据进行数字签名,以提供数据完整性,验证数据是否到达目标接收者之前被篡改过。
# 什么是HTTP?什么是HTTPS?
HTTP全称为 HyperText Transfer Protocol(超文本传输协议),它是一种用于网络传输数据的协议。(HTTP消息分为两种:请求和响应)(在OSI模型中,HTTP是第七层协议)
HTTPS全称为 HyperText Transfer Protocol Secure(超文本传输安全协议),支持加密和验证的HTTP,对比HTTP,HTTPS使用TLS来加密,对请求和响应进行数字签名,提供对网站服务器的身份认证,保护交换数据的隐私和完整性。(通俗来说,HTTPS = HTTP + SSL)
# 为什么HTTPS安全?
HTTP协议传输文本,是以明文形式发送的,监视连接的任何人都能读取它,因此,HTTP不安全,回到HTTPS,无法看到其真实内容,只有一堆随机字符
# keytool命令详解
1.生成pfx证书(.p12是pfx的新格式)
keytool -genkey
-alias laokou-nacos # 证书别名,不区分大小写
-storetype PKCS12 # 密钥库类型,常用类型有JKS、PKCS12
-keyalg RSA # 密钥算法,可选密钥算法:RSA\DSA,默认DSA
-keysize 2048 # 密钥长度(RSA=2048,DSA=2048)
-keystore scg-keystore.p12 # 密钥库文件名称
-validity 3650 # 证书有效天数
2.导出证书为cer(cer/crt是证书的公钥格式,cer是crt证书的微软形式)
keytool -exportcert -v
-alias laokou-nacos # 证书别名,不区分大小写
-keystore scg-keystore.p12 # 密钥库文件名称
-storepass laokou # 密钥库口令,推荐与keypass一致(获取keystore信息所需要密码)
-file register.cer # 导出的文件名
# SSL证书在微服务的应用
# 如何配置在yaml?
server:
ssl:
# 开启证书,true开启ssl false关闭ssl
enabled: true
# 证书位置(放在resource即可)(证书就是我上面写的命令来生成的)
key-store: classpath:scg-keystore.p12
# 证书别名
key-alias: laokou-nacos
# 秘钥类型
key-store-type: PKCS12
# 证书密码
key-store-password: laokou
# 服务间开启ssl,openfeign如何调用接口?
# 查看 FeignAutoConfiguration 源码
话不多说,给我怼源码(作者使用的okhttp,httpclient类似)
spirng:
cloud:
openfeign:
okhttp:
enabled: true
httpclient:
# 把disableSslValidationi设为true,就可以绕过ssl
disable-ssl-validation: true
# httpclient5访问https网站,绕过ssl单向认证
把 FeignAutoConfiguration 代码搬过来(嘿嘿,效率为王)
public class HttpUtil {
public static void main(String[] args) {
// 创建HttpClient对象
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
boolean disableSsl = true;
if (disableSsl) {
disableSsl(httpClientBuilder);
}
}
public static void disableSsl(HttpClientBuilder builder) {
// X.509是密码学里公钥证书的格式标准,作为证书标准
X509TrustManager disabledTrustManager = new DisableValidationTrustManager();
// 信任库
TrustManager[] trustManagers = new TrustManager[]{disabledTrustManager};
// 怎么选择加密协议,请看 ProtocolVersion
// 为什么能找到对应的加密协议 请查看 SSLContextSpi
SSLContext sslContext = SSLContext.getInstance(TLS_PROTOCOL_VERSION);
sslContext.init(null, trustManagers, new SecureRandom());
SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactoryBuilder.create()
.setSslContext(sslContext).setHostnameVerifier(new TrustAllHostnames()).build();
PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = PoolingHttpClientConnectionManagerBuilder
.create().setSSLSocketFactory(sslConnectionSocketFactory).build();
builder.setConnectionManager(poolingHttpClientConnectionManager);
}
static class DisableValidationTrustManager implements X509TrustManager {
DisableValidationTrustManager() {
}
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
}
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
static class TrustAllHostnames implements HostnameVerifier {
TrustAllHostnames() {
}
public boolean verify(String s, SSLSession sslSession) {
return true;
}
}
}
# nacos开启ssl,各个服务无法注册(使用cer)
查看issue nacos支持https (opens new window)
# 配置cer
// https://github.com/alibaba/nacos/pull/3654
// 请查看 HttpLoginProcessor
System.setProperty(TlsSystemConfig.TLS_ENABLE, TRUE);
System.setProperty(TlsSystemConfig.CLIENT_AUTH, TRUE);
# 确保文件位置填写正确
System.setProperty(TlsSystemConfig.CLIENT_TRUST_CERT, "tls/register.cer");
# yaml配置
# nacos使用https和http协议,只要注册临时服务,都是走RPC,因此使用https需要改为https
spring:
cloud:
# nacos
nacos:
discovery:
server-addr: https://127.0.0.1:8848
namespace: public
username: nacos
password: nacos
group: LAOKOU_GROUP
# https
secure: true
# true 临时 false 持久
ephemeral: true
config:
server-addr: https://127.0.0.1:8848
namespace: public
username: nacos
password: nacos
# https://github.com/alibaba/spring-cloud-alibaba/blob/2021.x/spring-cloud-alibaba-docs/src/main/asciidoc-zh/nacos-config.adoc
# 指定读取的文件格式
file-extension: yaml
group: LAOKOU_GROUP
refresh-enabled: true
# spring-boot-admin开启ssl,各个服务无法注册
# 查看 SpringBootAdminClientAutoConfiguration 源码
话不多说,给我怼源码
# 重写自动装配代码
@ComponentScan(value = "org.laokou.common.monitor")
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication
@AutoConfiguration
@Conditional(SpringBootAdminClientEnabledCondition.class)
@AutoConfigureAfter({WebEndpointAutoConfiguration.class, RestTemplateAutoConfiguration.class,
WebClientAutoConfiguration.class})
@EnableConfigurationProperties({ClientProperties.class, InstanceProperties.class, ServerProperties.class,
ManagementServerProperties.class})
public class SpringBootAdminClientAutoConfig {
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(RestTemplateBuilder.class)
public static class BlockingRegistrationClientConfig {
/**
* 阻塞
*/
@Bean
@ConditionalOnMissingBean
public RegistrationClient registrationClient(ClientProperties client) {
RestTemplateBuilder builder = new RestTemplateBuilder().setConnectTimeout(client.getConnectTimeout());
builder.setReadTimeout(client.getReadTimeout());
if (client.getUsername() != null && client.getPassword() != null) {
builder = builder.basicAuthentication(client.getUsername(), client.getPassword());
}
RestTemplate build = builder.build();
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// 直接使用我上面写的
HttpUtil.disableSsl(httpClientBuilder);
CloseableHttpClient closeableHttpClient = httpClientBuilder.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
closeableHttpClient);
build.setRequestFactory(requestFactory);
return new BlockingRegistrationClient(build);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnBean(WebClient.Builder.class)
@ConditionalOnMissingBean(RestTemplateBuilder.class)
public static class ReactiveRegistrationClientConfig {
/**
* 响应式
*/
@Bean
@ConditionalOnMissingBean
public RegistrationClient registrationClient(ClientProperties client, WebClient.Builder webClient)
throws SSLException {
if (client.getUsername() != null && client.getPassword() != null) {
webClient = webClient.filter(basicAuthentication(client.getUsername(), client.getPassword()));
}
SslContext context = SslContextBuilder.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
HttpClient httpClient = HttpClient.create().secure(t -> t.sslContext(context));
webClient.clientConnector(new ReactorClientHttpConnector(httpClient));
return new ReactiveRegistrationClient(webClient.build(), client.getReadTimeout());
}
}
}
# 自动装配
# 移除自动装配
@SpringBootApplication(exclude = { SpringBootAdminClientAutoConfiguration.class })
# gateway对下游服务不信任
查看spring官方文档 Gateway TLS 和 SSL (opens new window)
spring:
cloud:
gateway:
httpclient:
ssl:
useInsecureTrustManager: true
# 如何开启http2?
# 什么是http2?
HTTP/2是一种网络协议,是HTTP/1.1的升级版,为了提高web性能,减少延迟,增加安全性,使web应用更加快速,高效和可靠
# http2开启条件
开启条件,就是必须使用ssl证书才行,因此有上面的铺垫,我们可以很轻松的开启
# yaml配置
server:
http2:
enabled: true
补充一句,目前只限于tomcat和undertow
# 浏览器安装证书,信任自签名的HTTPS
# 创建证书(带域名)
keytool -genkey
-alias laokou-cert # 证书别名,不区分大小写
-storetype PKCS12 # 密钥库类型,可用类型:JKS,PKCS12
-keyalg RSA # 密钥的算法,如RSA,DSA,默认DSA
-keysize 2048 # 密钥长度(RSA=2048,DSA=2048)
-keystore scg-keystore.p12 密钥库文件名称
-validity 3650 # 有效期天数
-dname "CN=127.0.0.1,OU=laokouyun,O=laokouyun,L=Shenzhen,ST=Guangzhou,C=CN" # 发行者信息(CN必填)
-storepass laokou # 密钥库口令
-keypass laokou # 私钥密码
# 解释:-dname 构成
# CN = 域名或IP,必填,CN要和服务器的域名或IP保持一致
# OU = 组织单位名称
# O = 组织名称
# L = 城市或区域名称
# ST = 州或省份名称
# C = 国家简写(CN代表中国)
# 导出证书
keytool -exportcert -v
-alias laokou-cert # 证书别名,不区分大小写
-keystore scg-keystore.p12 # 密钥库文件名称
-storepass laokou # 密钥库口令
-file cert.cer # 证书名称
# 导入浏览器
- 打开浏览器,找到证书管理(略)
- 然后点下一步,直到完成导入(略)
# 服务端和客户端证书
=> laokou123【密码】
=> zh【国家】
=> laokouyun【地区、组织、名称】
=> 2413176044@qq.com【邮箱】
---开始---nacos-ca---开始---
注意:Country Name,State or Province Name,Organization Name
生成CA私钥:openssl genrsa -out nacos-ca-key.pem -aes128 2048
生成CA证书:openssl req -new -x509 -key nacos-ca-key.pem -out nacos-ca-cert.pem -days 3650
---结束---nacos-ca---结束---
---开始---nacos-server-cert---开始---
生成私钥:openssl genrsa -out nacos-server-key.pem -aes128 2048
生成签名:openssl req -new -key nacos-server-key.pem -out nacos-server-csr.pem
生成证书:openssl ca -in nacos-server-csr.pem -cert nacos-ca-cert.pem -keyfile nacos-ca-key.pem -out nacos-server-cert.pem -days 3650
报错修改:根据报错提醒创建/CA/newcerts并授权,创建index.txt和serial并写入01
---结束---nacos-server-cert---结束---
---开始---nacos-client-cert---开始---
生成私钥:openssl genrsa -out nacos-client-key.pem -aes128 2048
生成签名:openssl req -new -key nacos-client-key.pem -out nacos-client-csr.pem
生成证书:openssl ca -in nacos-client-csr.pem -cert nacos-ca-cert.pem -keyfile nacos-ca-key.pem -out nacos-client-cert.pem -days 3650
报错修改:根据报错提醒创建/CA/newcerts并授权,创建index.txt和serial并写入01
---结束---nacos-client-cert---结束---
我是老寇,我们下次再见啦!