【厨房测试系列】第一章 手撸压力机(四)- http证书认证的实现

本文涉及的产品
Digicert DV 证书 单域名,20个 3个月
简介: 我们知道通常https接口是通过ssl/tsl进行加密的,有时候我们的请求https接口需要进行验证,需要在客户端发送请求时,带上密钥对通过摘要算法计算出的摘要及明文进行加密,而服务端则通过密钥进行解密。

2000元阿里云代金券免费领取,2核4G云服务器仅664元/3年,新老用户都有优惠,立即抢购>>>


阿里云采购季(云主机223元/3年)活动入口:请点击进入>>>,


阿里云学生服务器(9.5元/月)购买入口:请点击进入>>>,

上一篇对http请求进行了封装,本章咱们接着往下进行,讲解可配置项高级选项,假如一个http接口需要进行验证,我们应该如何处理。
我们知道通常https接口是通过ssl/tsl进行加密的,有时候我们的请求https接口需要进行验证,需要在客户端发送请求时,带上密钥对通过摘要算法计算出的摘要及明文进行加密,而服务端则通过密钥进行解密。

而https在认证,又分为单向认证和双向认证:
单向认证:

  • 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
    服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
  • 客户端使用服务端返回的信息验证服务器的合法性,包括:
    • 证书是否过期
    • 发行服务器证书的CA是否可靠
    • 返回的公钥是否能正确解开返回证书中的数字签名
    • 服务器证书上的域名是否和服务器的实际域名相匹配
    • 验证通过后,将继续进行通信,否则,终止通信
  • 客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
  • 服务器端在客户端提供的加密方案中选择加密程度最高的加密方式。
  • 服务器将选择好的加密方案通过明文方式返回给客户端
  • 客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密的密钥,使用服务端返回的公钥进行加密,将加密后的随机码发送至服务器
  • 服务器收到客户端返回的加密信息后,使用自己的私钥进行解密,获取对称加密密钥。在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

双向认证:

  • 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。
  • 服务端给客户端返回SSL协议版本号、加密算法种类、随机数等信息,同时也返回服务器端的证书,即公钥证书
  • 客户端使用服务端返回的信息验证服务器的合法性,包括:
      - 证书是否过期
      - 发行服务器证书的CA是否可靠
      - 返回的公钥是否能正确解开返回证书中的数字签名
      - 服务器证书上的域名是否和服务器的实际域名相匹配
      - 验证通过后,将继续进行通信,否则,终止通信
    
  • 服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端
  • 验证客户端的证书,通过验证后,会获得客户端的公钥
  • 客户端向服务端发送自己所能支持的对称加密方案,供服务器端进行选择
  • 服务器端在客户端提供的加密方案中选择加密程度最高的加密方式
  • 将加密方案通过使用之前获取到的公钥进行加密,返回给客户端
  • 客户端收到服务端返回的加密方案密文后,使用自己的私钥进行解密,获取具体加密方式,而后,产生该加密方式的随机码,用作加密过程中的密钥,使用之前从服务端证书中获取到的公钥进行加密后,发送给服务端
  • 服务端收到客户端发送的消息后,使用自己的私钥进行解密,获取对称加密的密钥,在接下来的会话中,服务器和客户端将会使用该密码进行对称加密,保证通信过程中信息的安全。

这样,我们就能明白我们需要如何去设计自己的高级选项结构了,我们首先需要选择是单向认证还是双向认证。下面我们在http_model.go文件中新增:

// AdvancedOptions 高级选项
type AdvancedOptions struct {
        Tls Tls // 验证设置
}

// Tls tls认证结构体
type Tls struct {
        IsVerify   bool   // 是否开启验证,默认不开启,开启后需要上传密钥文件
        VerifyType int32  // 认证类型:0表示双向认证;1表示单向认证;默认为0
        CaCert     string // 密钥文件
}

同时我们修改http_model.go文件中HttpClientSettings结构体,修改后如下:

// HttpClientSettings http客户端设置
type HttpClientSettings struct {
        //  客户端的名称,在header中的user-agent使用,通常我们默认就好
        Name string

        // 默认为flase,表示User-Agent使用fasthttp的默认值
        NoDefaultUserAgentHeader bool

        // 每台主机可以建立的最大连接数。如果没有设置,则使用DefaultMaxConnsPerHost。
        MaxConnsPerHost int

        // 空闲的保持连接在此持续时间之后关闭。默认情况下,在DefaultMaxIdleConnDuration之后关闭空闲连接。
        // 该连接如果空闲的话,在此时间后断开。
        MaxIdleConnDuration int64

        // Keep-alive连接在此持续时间后关闭。默认情况下,连接时间是不限制的。
        MaxConnDuration int

        // 默认情况下,响应读取超时时间是不限制的。
        ReadTimeout int64
        // 默认情况下,请求写超时时间不受限制。
        WriteTimeout int64

        // 请求头是否按标准格式传输
        DisableHeaderNamesNormalizing bool
        // url路径是按照原样输出,还是按照规范化输出。默认按照规范化输出
        DisablePathNormalizing bool
        AdvancedOptions        AdvancedOptions   // 高级选项
}

这样我们就完成了对http客户端认证相关的高级设置选项结构完成了改造,那我们如何去使用这些设置呢,下面我们对新建http客户端的代码,进行优化,修改http_client.go文件中的newHttpClient()方法:
// 新建一个http客户端

func newHttpClient(httpClientSettings model.HttpClientSettings) (httpClient *fasthttp.Client) {
        // tls验证,关闭验证
        tr := &tls.Config{
                InsecureSkipVerify: true,
        }
        // 新建指针类型的客户端
        httpClient = &fasthttp.Client{}

        if httpClientSettings.Name != "" {
                httpClient.Name = httpClientSettings.Name
        }

        if httpClientSettings.NoDefaultUserAgentHeader == true {
                httpClient.NoDefaultUserAgentHeader = true
        }

        // 如果最大连接数不为0,将设置此数
        if httpClientSettings.MaxConnsPerHost != 0 {
                httpClient.MaxConnsPerHost = httpClientSettings.MaxConnsPerHost
        }

        // url不按照标准输出,按照原样输出
        if httpClientSettings.DisablePathNormalizing == true {
                httpClient.DisablePathNormalizing = true
        }
        // 请求头不按标准格式传输
        if httpClientSettings.DisableHeaderNamesNormalizing == true {
                httpClient.DisableHeaderNamesNormalizing = true
        }

        // 如果此时间不为0,那么将设置此时间。keep-alive维持此时长后将关闭。时间单位为毫秒
        if httpClientSettings.MaxConnDuration != 0 {
                httpClient.MaxConnDuration = time.Duration(httpClientSettings.MaxConnDuration) * time.Millisecond
        }

        if httpClientSettings.ReadTimeout != 0 {
                httpClient.ReadTimeout = time.Duration(httpClientSettings.ReadTimeout) * time.Millisecond
        }

        if httpClientSettings.WriteTimeout != 0 {
                httpClient.WriteTimeout = time.Duration(httpClientSettings.WriteTimeout) * time.Millisecond
        }

        // 该连接如果空闲的话,在此时间后断开。
        if httpClientSettings.MaxIdleConnDuration != 0 {
                httpClient.MaxIdleConnDuration = time.Duration(httpClientSettings.MaxIdleConnDuration) * time.Millisecond
        }

        // 
        httpsTls := httpClientSettings.AdvancedOptions.Tls

        // 如果开启认证
        if httpsTls.IsVerify {
                // switch条件选择语句,如果认证类型为0:则表示双向认证,如果是1:则表示为单向认证
                switch httpsTls.VerifyType {
                case 0: // 开启双向验证
                        tr.InsecureSkipVerify = false
                        // 如果密钥文件为空则跳出switch语句
                        if httpsTls.CaCert == "" {
                                break
                        }
                        // 生成一个cert对象池
                        caCertPool := x509.NewCertPool()
                        if caCertPool == nil {
                                fmt.Println("生成CertPool失败!")
                                break
                        }

                        // 读取认证文件,读出后为字节数组
                        key, err := ioutil.ReadFile(httpsTls.CaCert)
                        // 如果读取错误,则跳出switch语句
                        if err != nil {
                                fmt.Println("打开密钥文件失败: ", err.Error())
                                break
                        }
                        // 将认证文件添加到cert池中
                        ok := caCertPool.AppendCertsFromPEM(key)
                        // 如果添加失败则跳出switch语句
                        if !ok {
                                fmt.Println("密钥文件错误,生成失败!!!")
                                break
                        }
                        // 将认证信息添加到客户端认证结构体
                        tr.ClientCAs = caCertPool
                case 1: // 开启单向验证,客户端验证服务端密钥
                        tr.InsecureSkipVerify = false
                }
        }

        // 客户端认证配置项
        httpClient.TLSConfig = tr
        return
}

下面我们验证一下,我们的修改是否成功。
修改main.go文件,如下:

package main

import (
        "kitchen-engine/client"
        "kitchen-engine/model"
)

func main() {

        // 一个类型中的字段,可以重置,也可以使用默认值,在go中,所有的类型的初始值,都是字段类型的0值,比如string的初始值是""空字符串,int类型的初始值是0等等
        httpClientSettings := model.HttpClientSettings{
                Name:                     "测试厨房",
                NoDefaultUserAgentHeader: true,
                MaxConnDuration:          1000,
                AdvancedOptions: model.AdvancedOptions{
                        Tls: model.Tls{
                                IsVerify:   false,
                                VerifyType: 1,
                        },
                },
        }

        headers := []model.Header{
                model.Header{
                        Field: "name",
                        Value: "你好",
                },
        }

        httpRequest := model.HttpRequest{
                Name:               "planet",
                Url:                "https://www.baidu.com",
                Method:             "GET",
                HttpClientSettings: httpClientSettings,
                Headers:            headers,
        }

        client.RequestHttp(httpRequest)
}
相关实践学习
通过HTTPS加速网关快速部署网站加密
本实验指导您如何在HTTPS加速网关中添加域名,以及在添加域名后如何进行修改和重置。
相关文章
|
4天前
|
JSON 搜索推荐 网络协议
玩转curl指令—测试简单的HTTP接口
玩转curl指令—测试简单的HTTP接口
78 0
|
4天前
|
安全 生物认证 网络安全
HTTP 常见认证方式
HTTP 常见认证方式
|
4天前
|
安全 网络安全 数据安全/隐私保护
关于证书导致的 HTTP 421 错误
关于证书导致的 HTTP 421 错误
7 0
|
4天前
|
缓存 运维 Serverless
Serverless 应用引擎产品使用之在阿里函数计算中,使用签名认证调用HTTP触发器的步骤如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
301 7
|
4天前
|
弹性计算 运维 监控
|
4天前
|
运维 Serverless API
Serverless 应用引擎产品使用之阿里函数计算中要关掉http触发器的jwt认证才可以进行性能探测如何解决
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
16 1
|
4天前
|
JSON 测试技术 API
Python的Api自动化测试使用HTTP客户端库发送请求
【4月更文挑战第18天】在Python中进行HTTP请求和API自动化测试有多个库可选:1) `requests`是最流行的选择,支持多种请求方法和内置JSON解析;2) `http.client`是标准库的一部分,适合需要低级别控制的用户;3) `urllib`提供URL操作,适用于复杂请求;4) `httpx`拥有类似`requests`的API,提供现代特性和异步支持。根据具体需求选择,如多数情况`requests`已足够。
16 3
|
4天前
Swagger基本使用与RestTemplate发送http接口测试
Swagger基本使用与RestTemplate发送http接口测试
21 1
|
4天前
|
域名解析 网络协议 应用服务中间件
阿里云SSL证书配置(HTTPS证书配置)
该内容是一个关于如何在阿里云上准备和购买SSL证书,以及如何为网站启用HTTPS的步骤指南。首先,需要注册并实名认证阿里云账号,然后在SSL证书控制台选择证书类型、品牌和时长进行购买。申请证书时填写域名信息,并进行DNS验证,这包括在阿里云域名管理板块添加解析记录。完成验证后提交审核,等待证书审核通过并下载Nginx格式的证书文件。最后,将证书配置到网站服务器以启用HTTPS。整个过程涉及账户注册、实名认证、证书购买、DNS设置和证书下载及安装。
176 0
|
4天前
|
网络安全 数据安全/隐私保护 Docker
免费的HTTPS证书
免费的HTTPS证书
101 1

热门文章

最新文章

http://www.vxiaotou.com