在互联网环境中,数据安全是每个开发者和用户都会关注的核心问题。HTTPS(HyperText Transfer Protocol Secure)是一种基于加密传输的网络协议,是应用层保护通信安全、防止数据被窃听和篡改的主要手段。
在很多一线企业,例如腾讯、阿里、字节等,许多应用强制要求使用 HTTPS 协议进行通信,Kubernetes 也提倡通过 HTTPS 协议进行通信。那么,为什么建议通过 HTTPS 协议而非 HTTP 协议?这源于二者的核心区别:
- HTTP 协议以明文方式传输数据,在网络中传输时可能遭受窃听、篡改或冒充攻击,安全性较低,存在数据泄露风险;
- HTTPS 协议基于 HTTP 协议增加了 SSL 安全层,通过加密通道传输数据,安全性更高。
通常,HTTPS 协议主要实现以下两类功能:
- 数据传输加密:通过 HTTPS 传输的数据始终以加密形式存在,确保信息安全;
- 身份认证:HTTPS 支持单向认证和双向认证。单向认证用于验证服务端的真实性,双向认证则同时验证服务端和客户端的合法性。
在实际的企业应用中,HTTPS 的使用方式主要包括:
- 利用 HTTPS 的数据加密能力,启用单向认证验证服务端的合法性,客户端认证则采用其他方式,例如 Bearer 认证。miniblog 项目采用的正是这种方式;
- 利用 HTTPS 的数据加密能力,同时通过双向认证验证服务端和客户端的合法性。
由于 CA 认证和 HTTPS 认证流程经常在面试中被考察,同时 miniblog 在启用 HTTPS 服务时需要理解相关内容。接下来,本课程将对这两部分进行详细介绍。
什么是 HTTPS?
HTTPS 是 HTTP(超文本传输协议)的安全版本。它通过在 HTTP 和传输层之间加入 SSL/TLS(安全套接字层/传输层安全协议)来确保通信安全。相比 HTTP,HTTPS 增加了三项核心功能:
- 数据加密:通过加密技术,确保通信内容不会被第三方窃听;
- 身份验证:通过服务器证书验证服务器身份,防止中间人攻击;
- b 校验数据是否在传输过程中被篡改。
使用 HTTPS 后,数据从客户端到服务器的整个过程都被加密保护,只有通信双方才能解码数据。
认识 CA 证书
CA 证书的内容较多,可以从以下四个方面掌握 CA 证书相关知识:
- CA 证书相关名词;
- CA 证书签发流程;
- CA 证书认证流程;
- CA 证书签发实战。
CA 证书相关名词
CA 证书涉及众多名词,以下整理了一些核心名词,供参考:
- CA:数字证书认证机构(Certificate Authority,简称 CA),是负责发放和管理数字证书的权威机构,作为受信任的第三方,承担公钥体系中公钥合法性检验的职责;
- CA 证书:CA 证书是由 CA 签发的数字证书,其格式可能有所不同,目前最常使用的是 X.509 证书格式;
- 公钥和私钥:公钥(Public Key)和私钥(Private Key)是一对密钥,通过特定算法生成。公钥是密钥对中公开的部分,通常用于加密会话密钥、验证数字签名或加密需通过相应私钥解密的数据;私钥则是非公开的部分;
- 加密算法:可以使用多种加密算法对数据进行加密。常见的加密算法包括以下两类:
- 对称加密:只有一个密钥进行加密和解密,密钥相同且加解密速度较快。典型的对称加密算法包括 DES 和 AES 等;
- b 密钥以成对形式出现(公钥和私钥),公钥和私钥互为匹配,且无法通过公钥推导出私钥,反之亦然。公钥用于加密时需通过私钥解密,私钥用于加密时需通过公钥解密。与对称加密相比,其速度较慢。典型非对称加密算法包括 RSA 和 DSA 等。
- X.509 证书编码格式:X.509 证书可能采用不同的编码规则。目前编码格式主要包括以下两种:
- PEM(Privacy Enhanced Mail):文本格式,文件后缀为 .pem,以 -----BEGIN XXXXXX----- 开头,-----END XXXXXX----- 结尾,内容为 BASE64 编码。多用于 Apache 和 UNIX 服务器;
- DER(Distinguished Encoding Rules):二进制格式,文件后缀为 .der,不可读。多用于 Java 和 Windows 服务器。
- X.509 证书文件后缀:X.509 证书的文件后缀不一定是 .pem 或 .der,以下是常见类型:
- CRT(.crt):代表 Certificate,意为证书,常见于 UNIX 系统,可能采用 PEM 或 DER 编码,大多数为 PEM 编码;
- CER(.cer):代表 Certificate,意为证书,常见于 Windows 系统,可能采用 PEM 或 DER 编码,大多数为 DER 编码;
- KEY(.key):通常存放公钥或私钥,虽非 X.509 证书,但其编码格式可能为 PEM 或 DER;
- CSR(.csr):Certificate Signing Request,即证书签名请求。CSR 不是证书,而是向权威证书颁发机构申请签名证书的请求,其主要包含一个公钥及附加信息。在生成申请时,会同时生成一个私钥,需自行妥善保管,无需提交给 CA 机构。
需要特别注意的是,如果证书文件的后缀是.pem 或.der,在文件名中应体现文件所属类别,例如:server-key.pem 表示私钥文件,server-crt.pem 表示证书文件。
为了更好地理解 CA 相关内容,接下来将以 CA 的签发流程为主线,在介绍流程的同时,阐述相关概念,CA 的认证流程实际上也是 HTTPS 的认证流程。
CA 证书的签发流程
CA 证书认证流程如图 11-2 所示。
图 11-2 CA 认证流程
图 11-2 所示的流程解释如下:
- 服务端向第三方机构 CA 提交公钥、组织信息、个人信息(如域名)等内容并申请认证(无需提交私钥);
- CA 通过线上、线下等多种手段验证申请者提供信息的真实性,例如确认组织是否存在、企业是否合法、是否拥有域名的所有权等;
- 如果信息审核通过,CA 会向申请者签发认证文件(证书):
- 证书包含以下信息:申请者的公钥、组织信息和个人信息、签发机构 CA 的信息、证书有效期、证书序列号等明文信息,同时还包含一个签名;
- 签名的生成算法:首先,使用散列函数计算明文信息的信息摘要,然后,采用 CA 的私钥对信息摘要进行加密,生成的密文即为签名。
- 客户端向服务端发出请求后,服务端返回服务端的证书文件;
- 客户端读取服务端证书中的明文信息,并使用相同的散列函数计算信息摘要。随后,利用对应 CA 的公钥解密签名数据并对比信息摘要。如果两者一致,则可以确认证书的合法性,即公钥合法。同时,客户端还需验证证书中的域名信息、有效期等内容。客户端通常内置信任 CA 的根证书(包含公钥),如果 CA 不被信任,则无法找到对应 CA 的证书,该证书将被判定为非法;
- 客户端生成一个随机数 R,并用服务端证书中的公钥加密后发送给服务端。服务端使用其私钥解密获取随机数 R,随后双方使用对称加密算法进行数据交换。
提示:证书由以下部分组成:公钥(服务端生成的密钥对中的公钥)+申请者与颁发者信息+签名(使用 CA 机构生成的密钥对中的私钥进行签名)。颁发证书的过程实际上是 CA 使用其私钥对证书请求文件进行签名。
CA 认证流程
CA 证书的认证分为单向认证和双向认证。在实际开发中,可根据需要自行选择:
- 单向认证:适用于无需在通信层对用户身份进行验证的场景,一般在应用逻辑层保证用户的合法登录。单向认证也是企业应用中,使用最多的认证方式;
- 双向认证:要求通信双方相互验证身份。例如,在企业应用服务之间存在互调关系时,可能需要对通信双方进行身份验证。
(1)单向认证流程
单向认证流程如图 11-3 所示。
图 11-3 单向认证流程
图 11-3 已经清晰的展示了单向流程的步骤,这里不再详解。需要注意的是第 3 步使用的是 CA 机构证书(根证书)的公钥来解密签名。
通过上述单向认证流程可以看出,整个流程需要以下三个证书文件:根证书、服务器端公钥证书、服务器端私钥文件。
(2)双向认证流程
单向认证仅验证了服务端的身份。如果有人冒充客户端,该如何应对?此时可以采用双向认证。
双向认证 SSL 握手过程与单向认证有所不同,其大部分步骤与单向认证过程相同。但在客户端成功验证服务器后,新增了服务器验证客户端的流程步骤。双向认证流程如图 11-4 所示。
图 11-4 双向认证流程
通过上述双向认证流程可以看出,整个双向认证过程需要 5 个证书文件:根证书、服务器端公钥证书、服务器端私钥文件、客户端公钥证书、客户端私钥文件。
CA 证书签发实战
CA 证书由权威的 CA 机构签发,其签发流程较为复杂且费用较高。在后端应用开发中,通常由开发或运维人员自行生成根证书及其私钥,并扮演 CA 的角色,负责为其他服务端和客户端签发证书,此类证书也称为自签证书。
在企业应用开发中,可以使用 openssl 工具来签发根证书、服务端证书和客户端证书。使用 openssl 工具签发证书具体包括以下几步:
- 签发根证书和私钥;
- 生成服务端证书;
- 生成客户端证书;
步骤一:签发根证书和私钥
签发根证书和私钥包括以下 3 步操作:生成根证书私钥、生成请求文件、生成根证书。
(1)生成根证书私钥
使用以下命令生成根证书私钥:
$ openssl genrsa -out ca.key 1024genrsa 子命令主要用于生成 RSA 私钥。命令行格式:openssl genrsa [args] [numbits]。涉及参数说明如下:
- -out file:将生成的私钥保存至指定的文件中;
- numbits:指定生成私钥的大小,默认是 2048。
(2)生成请求文件
使用证书私钥生成请求文件,命令如下:
$ openssl req -new -key ca.key -out ca.csr -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=devops/OU=it/CN=127.0.0.1/emailAddress=colin404@foxmail.com"req 子命令主要用于创建证书请求文件,其命令行格式为:openssl req [options] <infile> outfile。参数说明如下:
- -new:创建新的证书请求文件;
- -key file:指定创建证书请求所使用的私钥文件;
- -out arg:指定输出文件路径;
- -subj arg:设置或修改证书请求中的主体信息。
证书请求的主体信息选项说明如下:
- CN(Common Name):指定证书中标识身份的名称,该名称必须唯一。通常填写需要申请 SSL 证书的域名(domain)或子域名(subdomain);
- C(Country):国家代码;
- ST(State):州或省;
- L(Locality):城市;
- O(Organization):组织名称;
- OU(Organizational Unit):组织单位名称。
提示:不同证书的 CSR 文件,其 CN、C、ST、L、O、OU 的组合必须不同。在创建后续证书的 CSR 文件时,CN 必须各不相同,而 C、ST、L、O 和 OU 可以相同,以实现区分证书的目的。
(3)生成根证书
执行以下命令生成根证书:
$ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crtx509 命令主要用于创建和修改 x509 证书,其命令行格式如下:openssl x509 [options] <infile> outfile。参数说明如下:
- -in arg:指定输入文件,默认为标准输入;
- -out arg:指定输出文件,默认为标准输出;
- -req:指定输入文件为证书请求;
- -signkey arg:指定用于自签名的私钥文件;
- -CA arg:设置 CA 文件,必须为 PEM 格式;
- -CAkey arg:设置 CA 私钥文件,必须为 PEM 格式;
- -CAcreateserial:创建序列号文件。
步骤二:生成服务端证书
执行以下命令来生成服务端证书:
# 1. 生成服务端私钥
$ openssl genrsa -out server.key 1024
# 2. 生成服务端公钥
$ openssl rsa -in server.key -pubout -out server.pem
# 3. 生成服务端向 CA 申请签名的 CSR
$ openssl req -new -key server.key -out server.csr -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=serverdevops/OU=serverit/CN=127.0.0.1/emailAddress=nosbelm@qq.com"
# 4. 生成服务端带有 CA 签名的证书
$ openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in server.csr -out server.crt上述命令中,rsa 子命令主要用于处理 RSA 公私钥文件。命令行格式:openssl rsa [options] <infile> outfile。涉及参数说明如下:
- -in arg: 指定输入文件;
- -pubout:指定输出文件为公钥,默认为私钥;
- -out arg:指定输出文件。
步骤三:生成客户端证书
执行以下命令来生成客户端证书:
# 1. 生成客户端私钥
$ openssl genrsa -out client.key 1024
# 2. 生成客户端公钥
$ openssl rsa -in client.key -pubout -out client.pem
# 3. 生成客户端向 CA 申请签名的 CSR
$ openssl req -new -key client.key -out client.csr -subj "/C=CN/ST=Guangdong/L=Shenzhen/O=clientdevops/OU=clientit/CN=127.0.0.1/emailAddress=nosbelm@qq.com"
# 4. 生成客户端带有 CA 签名的证书
$ openssl x509 -req -CA ca.crt -CAkey ca.key -CAcreateserial -in client.csr -out client.crtminiblog 实现 HTTPS 通信
miniblog 利用 HTTPS 的数据传输加密能力,启用 HTTPS 单向认证以验证服务端的合法性。同时,服务端对客户端的认证采用 JWT Token 认证。功能实现流程分为以下三个步骤:
- 生成根证书、服务端证书和服务端私钥;
- 实现服务器以 TLS 模式通信;
- miniblog 添加 TLS 初始化配置。
生成根证书、服务端证书和服务端私钥
在 Makefile 文件中添加 ca 伪目标,用于自动生成所需的 CA 证书文件:
...
# 将 Makefile 中的 Shell 切换为 bash
SHELL := /bin/bash
...
.PHONY: ca
ca: # 生成 CA 文件.
@mkdir -p $(OUTPUT_DIR)/cert
@# 1. 生成根证书私钥 (CA Key)
@openssl genrsa -out $(OUTPUT_DIR)/cert/ca.key 4096
@# 2. 使用根私钥生成证书签名请求 (CA CSR),有效期为 10 年
@openssl req -new -nodes -key $(OUTPUT_DIR)/cert/ca.key -sha256 -days 3650 -out $(OUTPUT_DIR)/cert/ca.csr \
-subj "/C=CN/ST=Guangdong/L=Shenzhen/O=onexstack/OU=it/CN=127.0.0.1/emailAddress=colin404@foxmail.com"
@# 3. 使用根私钥签发根证书 (CA CRT),使其自签名
@openssl x509 -req -days 365 -in $(OUTPUT_DIR)/cert/ca.csr -signkey $(OUTPUT_DIR)/cert/ca.key -out $(OUTPUT_DIR)/cert/ca.crt
@# 4. 生成服务端私钥
@openssl genrsa -out $(OUTPUT_DIR)/cert/server.key 2048
@# 5. 使用服务端私钥生成服务端的证书签名请求 (Server CSR)
@openssl req -new -key $(OUTPUT_DIR)/cert/server.key -out $(OUTPUT_DIR)/cert/server.csr \
-subj "/C=CN/ST=Guangdong/L=Shenzhen/O=serverdevops/OU=serverit/CN=localhost/emailAddress=colin404@foxmail.com" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1"
@# 6. 使用根证书 (CA) 签发服务端证书 (Server CRT)
@openssl x509 -days 365 -sha256 -req -CA $(OUTPUT_DIR)/cert/ca.crt -CAkey $(OUTPUT_DIR)/cert/ca.key \
-CAcreateserial -in $(OUTPUT_DIR)/cert/server.csr -out $(OUTPUT_DIR)/cert/server.crt -extensions v3_req \
-extfile <(printf "[v3_req]\nsubjectAltName=DNS:localhost,IP:127.0.0.1")实现服务器以 TLS 模式通信
分别修改 internal/pkg/server/ 目录下的 grpc_server.go、http_server.go、reverse_proxy_server.go 文件,实现服务器以 TLS 模式通信。
(1)实现 gRPC 服务器以 TLS 模式通信
修改 internal/pkg/server/grpc_server.go 文件,实现 gRPC 服务器以 HTTPS 通信模式启动,代码变更如下:
import (
...
"google.golang.org/grpc/credentials"
...
)
...
// NewGRPCServer 创建一个新的 GRPC 服务器实例.
func NewGRPCServer(
...
tlsOptions *genericoptions.TLSOptions,
...
) (*GRPCServer, error) {
...
if tlsOptions != nil && tlsOptions.UseTLS {
tlsConfig := tlsOptions.MustTLSConfig()
serverOptions = append(serverOptions, grpc.Creds(credentials.NewTLS(tlsConfig)))
}
grpcsrv := grpc.NewServer(serverOptions...)
...
}*genericoptions.TLSOptions 结构体类型包含了 TLS 的配置项,其定义如下:
// TLSOptions is the TLS cert info for serving secure traffic.
type TLSOptions struct {
// UseTLS specifies whether should be encrypted with TLS if possible.
UseTLS bool
InsecureSkipVerify bool
CaCert string
Cert string
Key string
}TLSOptions 结构体中各个字段释义如下:
- UseTLS:指定是否启用 TLS,也即使用 HTTPS 协议通信;
- InsecureSkipVerify:指定是否跳过证书校验。如果为 true,则在客户端验证服务端证书时,会忽略证书的真实性或有效性。这通常用于测试环境下规避自签名证书验证问题,但在生产环境中应谨慎使用;
- CaCert:设置 CA(证书颁发机构)证书的文件路径,用于验证 TLS 连接中的对端(服务端或客户端)证书是否受信任;
- Cert:设置客户端或服务端的证书文件路径;
- Key:与 Cert 对应的私钥文件路径,用于证明证书持有者的身份以及完成 TLS 握手过程。
TLSOptions 结构体包含了 MustTLSConfig 方法,该方法可以基于 TLSOptions 中的字段生成 *tls.Config 类型的实例,*tls.Config 用来配置 HTTP 服务器是否以 TLS 模式启动。
(2)实现 HTTP 服务器以 TLS 模式通信
修改 internal/pkg/server/http_server.go 文件,实现 HTTP 服务器以 TLS 通信模式启动,代码变更如下:
import (
...
"crypto/tls"
...
)
...
// NewHTTPServer 创建一个新的 HTTP 服务器实例.
func NewHTTPServer(httpOptions *genericoptions.HTTPOptions, tlsOptions *genericoptions.TLSOptions, handler http.Handler) *HTTPServer {
var tlsConfig *tls.Config
if tlsOptions != nil && tlsOptions.UseTLS {
tlsConfig = tlsOptions.MustTLSConfig()
}
return &HTTPServer{
srv: &http.Server{
...
TLSConfig: tlsConfig,
},
}
}
// RunOrDie 启动 HTTP 服务器并在出错时记录致命错误.
func (s *HTTPServer) RunOrDie() {
log.Infow("Start to listening the incoming requests", "protocol", protocolName(s.srv), "addr", s.srv.Addr)
// 默认启动 HTTP 服务器
serveFn := func() error { return s.srv.ListenAndServe() }
if s.srv.TLSConfig != nil {
serveFn = func() error { return s.srv.ListenAndServeTLS("", "") }
}
if err := serveFn(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalw("Failed to server HTTP(s) server", "err", err)
}
}上述代码,创建了 *tls.Config 类型的实例 tlsConfig,并使用 tlsConfig 设置 http.Server 的 TLSConfig 字段,以此开启 HTTP 服务器的 TLS 通信模式。在 RunOrDie 方法中,判断如果开启了 TLS 通信模式,则使用 *http.Server 类型实例的 ListenAndServeTLS 来启动 HTTP 服务器,否则使用 ListenAndServe 方法。
(3)实现 HTTP 反向代理服务器以 TLS 模式通信
修改 internal/pkg/server/reverse_proxy_server.go 文件,实现 HTTP 反向代理服务器以 TLS 通信模式启动,代码变更如下:
import (
...
"crypto/tls"
...
"google.golang.org/grpc/credentials"
...
)
...
// NewGRPCGatewayServer 创建一个新的 GRPC 网关服务器实例.
func NewGRPCGatewayServer(
...
tlsOptions *genericoptions.TLSOptions,
...
) (*GRPCGatewayServer, error) {
var tlsConfig *tls.Config
if tlsOptions != nil && tlsOptions.UseTLS {
tlsConfig = tlsOptions.MustTLSConfig()
tlsConfig.InsecureSkipVerify = true
}
...
if tlsConfig != nil {
dialOptions = append(dialOptions, grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig)))
} else {
dialOptions = append(dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))
}
...
return &GRPCGatewayServer{
srv: &http.Server{
...
TLSConfig: tlsConfig,
},
}, nil
}
// RunOrDie 启动 GRPC 网关服务器并在出错时记录致命错误.
func (s *GRPCGatewayServer) RunOrDie() {
log.Infow("Start to listening the incoming requests", "protocol", protocolName(s.srv), "addr", s.srv.Addr)
// 默认启动 HTTP 服务器
serveFn := func() error { return s.srv.ListenAndServe() }
if s.srv.TLSConfig != nil {
serveFn = func() error { return s.srv.ListenAndServeTLS("", "") }
}
if err := serveFn(); err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Fatalw("Failed to server HTTP(s) server", "err", err)
}
}miniblog 添加 TLS 初始化配置
在启动服务器时,需要加载 TLS 的配置。所以,miniblog 的初始化配置还需要支持 TLS 相关配置。TLS 初始化配置,实现方式跟其他初始化配置实现方式相同,本节不再详细介绍。
测试 TLS 通信功能
在以 TLS 通信模式启动服务器时,需要先生成 CA 证书文件,通过执行以下命令来生成并安装 CA 证书文件:
$ git checkout feature/s26 # 切换到对应的分支,或者master分支
$ make ca
$ cp -a _output/cert/ $HOME/.miniblog/配置 $HOME/.miniblog/mb-apiserver.yaml 文件,启用 Gin 服务器模式,并开启 TLS 通信模式、设置 TLS 服务器监听端口,配置如下:
server-mode: gin
# ...
# 安全服务器相关配置
tls:
# 是否启动 HTTPS 安全服务器
# 生产环境建议开启 HTTPS。并使用 HTTPS 协议访问 API 接口
use-tls: true
# 证书
cert: $HOME/.miniblog/cert/server.crt
# 证书 Key 文件
key: $HOME/.miniblog/cert/server.key
# HTTP 服务器相关配置
http:
# HTTP 服务器监听地址
addr: :5555注意,需要将 tls.cert 和 tls.key 中的 $HOME,替换为当前用户的主目录路径。配置文件识别不了$HOME 这种路径表示方式。上述配置中,开启后的 HTTPS 服务器监听端口为 5555。
配置完配置文件后,便可以执行以下命令编译并启动服务器:
$ make build
$ _output/mb-apiserver
...
{"level":"info","timestamp":"2025-02-01 17:56:46.761","caller":"server/http_server.go:43","message":"Start to listening the incoming requests","protocol":"https","addr":":5555"}从输出的日志可以知道服务器以 TLS 通信模式监听在 5555 端口上。
新打开一个 Linux 终端。并执行以下操作:
# 1. 通过 HTTP 协议访问 /healthz,协议不对报错
$ curl http://127.0.0.1:5555/healthz
Client sent an HTTP request to an HTTPS server.
# 2. 通过 HTTPS 协议访问 /healthz,不指定根证书,无法认证服务端证书报错
$ curl https://127.0.0.1:5555/healthz
curl: (60) SSL certificate problem: EE certificate key too weak
More details here: https://curl.haxx.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
# 3. 读取根证书,并使用根证书认证服务端
$ curl https://127.0.0.1:5555/healthz --ciphers DEFAULT@SECLEVEL=1 --cacert $HOME/.miniblog/cert/ca.crt
{"timestamp":"2025-02-01 17:57:37"}
# 4. 忽略 HTTPS 证书参数,指定跳过 SSL 检测
$ curl https://127.0.0.1:5555/healthz -k
{"timestamp":"2025-02-01 17:57:52"}上述代码脚本位于 feature/s26 分支的 scripts/test_tls.sh 文件中。上述测试执行了以下 4 类测试:
- 使用 HTTP 协议访问 /healthz 接口:因为服务器协议是 HTTPS,导致请求报错;
- 通过 HTTPS 协议访问 /healthz,不指定根证书:服务器使用了自签名的证书,curl 默认会验证服务端证书的合法性,因为未指定客户端使用的信任根证书,导致客户端无法验证服务端证书的合法性,请求报错;
- 通过 HTTPS 协议访问 /healthz,指定根证书:使用 --cacert 指定了客户端用于验证服务端证书的根证书路径。添加了 --ciphers DEFAULT@SECLEVEL=1 参数,用于调整安全级别,以适配可能较弱的加密配置。通信方式正确,请求成功;
- 忽略 HTTPS 证书参数,指定跳过 SSL 检测:使用了 -k(--insecure)选项,跳过服务端证书验证。
小结
本节课围绕应用安全的设计与实现,重点介绍了认证、授权以及 HTTPS 协议通信的具体实现方法。在认证功能中,miniblog 采用了基于用户名和密码的基础认证结合 JWT 令牌的方式,通过 JWT 的无状态性、离线验证和灵活性,提升了认证的效率和安全性,同时通过 gRPC 拦截器和 Gin 中间件实现了认证逻辑的统一管理。在授权功能中,miniblog 基于 RBAC 模型引入了 Casbin 框架,通过定义角色和权限策略,实现了对不同 API 接口的精细化访问控制,并通过中间件加载授权逻辑,保证了请求的安全性和灵活性。
此外,miniblog 通过启用 HTTPS 协议实现了通信加密,确保数据传输的机密性、完整性和身份验证能力。通过生成自签名证书并在 gRPC 和 HTTP 服务器中配置 TLS,系统实现了单向认证的安全通信,进一步提升了服务的安全性。通过这些功能的设计与实现,miniblog 在认证、授权和数据传输安全方面构建了完善的安全体系,为现代企业应用提供了可靠的安全保障。