grpc、https、oauth2等认证专栏实战8:https单向认证 介绍

发布于:2023-01-08 ⋅ 阅读:(533) ⋅ 点赞:(0)

已发表的技术专栏(订阅即可观看所有专栏)
0  grpc-go、protobuf、multus-cni 技术专栏 总入口

1  grpc-go 源码剖析与实战  文章目录

2  Protobuf介绍与实战 图文专栏  文章目录

3  multus-cni   文章目录(k8s多网络实现方案)

4  grpc、oauth2、openssl、双向认证、单向认证等专栏文章目录


1、简单介绍单向认证

  • 一般情况下,客户端需要验证服务器端的证书,服务器端不需要验证客户端的证书
  • 服务器端需要加载服务器端的证书,用以向客户端发送自己的证书
  • 客户端,主要分为两种情况
    • 客户端必须验证服务器端的证书
      • 可以通过写代码的方式来验证服务器端的证书
      • 可以通过curl方式来验证服务器端的证书
      • 可以通过Postman方式来验证服务器端的证书
    • 客户端不用证服务器端的证书

2、证书制作

单向认证时,服务器端的证书,可以使用自签证书,也可以使用非自签证书

2.1、方式一:使用自签证书,作为服务器端的证书

就是自己给自己颁发证书

openssl req -newkey rsa:2048 -nodes -keyout server.key -x509 -days 365 -out server.crt -subj "/C=CN/ST=beijing/L=beijing/O=baidu/OU=bigdata/CN=www.golang-study.com/emailAddress=123456789@qq.com"

在这里插入图片描述

查看生成的证书

openssl x509 -in server.crt -noout -text 

在这里插入图片描述

2.2、方式二:使用非自签方式

2.2.1、制作根证书

一次性方式生成根证书

openssl req -newkey rsa:2048 -nodes -keyout ca.key -x509 -days 365 -out ca.crt -subj "/C=CN/ST=beijing/L=beijing/O=baidu/OU=bigdata/CN=www.golang.com/emailAddress=000000@qq.com"

在这里插入图片描述

2.2.2、制作服务器端证书

2.2.2.1、第一步:生成服务器端密钥和服务器端证书签名 (SAN类型,即多个域名生效)

openssl req -newkey rsa:2048 -nodes -keyout server.key \
    -subj "/C=CN/ST=beijing/L=beijing/O=baidu/OU=bigdata/CN=www.golang-server.com/emailAddress=123456789@qq.com" \
    -reqexts SAN \
    -config <(cat /etc/pki/tls/openssl.cnf <(printf "\n[SAN]\nsubjectAltName=DNS:*.org.golang-server.com,DNS:www.golang-server.cn")) \
    -out server.csr

在这里插入图片描述

查看证书签名里,是否有SAN请求信息

openssl req -noout -text -in server.csr

在这里插入图片描述

2.2.2.2、第二步:根据CA证书,来颁发服务器端证书

openssl x509 -req -days 365 \
  -in server.csr -out server.crt \
  -CA ca.crt -CAkey ca.key -CAcreateserial \
  -extensions SAN \
  -extfile <(cat /etc/pki/tls/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:*.org.golang-server.com,DNS:www.golang-server.cn"))

在这里插入图片描述

查看生成的证书

openssl x509 -in server.crt -noout -text 

在这里插入图片描述

3、服务器端

注意,本次测试是单向认证测试。

服务器端不需要验证客户端的证书,因此,服务器端不需要加载根证书。

只需要加载服务器端的证书即可。

(在服务器端,根证书是用来验证客户端证书是否有效的。)

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"github.com/gorilla/mux"
	"log"
	"net/http"
)

var (
	port       int
	hostname   string
	serverKey  string
	serverCert string
)

func init() {
	flag.IntVar(&port, "port", 8080, "监听端口")
	flag.StringVar(&hostname, "hostname", "0.0.0.0", "服务地址")
	flag.StringVar(&serverKey, "serverKey", "8-WithTransportCredentials/https/one-way-authentication/tls/cert/server.key", "服务器密钥")
	flag.StringVar(&serverCert, "serverCert", "8-WithTransportCredentials/https/one-way-authentication/tls/cert/server.crt", "服务器证书")
}

func startHttpsServer(address string, serverCert string, serverKey string, router *mux.Router) {
	s := &http.Server{
		Addr:    address,
		Handler: router,
	}
	err := s.ListenAndServeTLS(serverCert, serverKey)
	if err != nil {
		log.Fatalln("ListenAndServeTLS err:", err)
	}
}

func SayHelloOpenssl(w http.ResponseWriter, r *http.Request) {
	log.Println("Entry SayHello")
	res := map[string]string{"hello": "单向认证OK"}

	b, err := json.Marshal(res)
	if err == nil {
		w.WriteHeader(http.StatusOK)
		w.Header().Set("Content-Type", "application/json")
		w.Write(b)
	}

	log.Println("Exit SayHello")
}

func main() {
	flag.Parse()

	router := mux.NewRouter().StrictSlash(true)
	router.HandleFunc("/svc/hello-openssl", SayHelloOpenssl).Methods("GET")

	var address = fmt.Sprintf("%s:%d", hostname, port)
	fmt.Println("Server listen on", address)
	startHttpsServer(address, serverCert, serverKey, router)

	fmt.Println("Exit main")
}

在单向认证测试中,服务器端最大的不同,就是下面的语句:

其他地方,就是普通的http例子

在这里插入图片描述

4、客户端

4.1、客户端必须验证服务器端证书

  • 如果服务器端一侧加载的是自签证书的话,客户端一侧,需要加载的是服务器的证书,用服务器端的证书来验证服务器端的证书,自己验证自己
  • 如果服务器端一侧加载的是非自签证书的话,客户端一侧,需要加载根证书,或者颁发服务器端证书的证书

4.1.1、使用go语言编写客户端验证服务器端证书

由于非自签的服务器端证书,是SAN类型的。

即,添加了多个域名,为了测试多个域名,

客户端采用了测试组的方式进行域名测试

package main

import (
	"crypto/tls"
	"crypto/x509"
	"fmt"
	"io/ioutil"
	"net/http"
	"testing"
)

var client *http.Client

func init() {
	pool := x509.NewCertPool()
	caCertPath := "***注意这里****改成自己的实际地址(有可能是ca的绝对地址)/cert/ca.crt"
	caCrt, err := ioutil.ReadFile(caCertPath)
	if err != nil {
		fmt.Println("ReadFile err:", err)
		return
	}
	pool.AppendCertsFromPEM(caCrt)

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			RootCAs: pool,
		},
	}

	client = &http.Client{Transport: tr}
}

// 测试单向认证
func TestOneWayAuthentication(t *testing.T) {
	type test struct { // 定义test结构体
		url string
	}
	tests := map[string]test{ // 测试组
		"test1": {url: "https://www.golang-server.cn:8080/svc/hello-openssl"},
		"test2": {url: "https://www.golang-server.com:8080/svc/hello-openssl"},
		"test3": {url: "https://abc.org.golang-server.com:8080/svc/hello-openssl"},
		"test4": {url: "https://www.golang-server.cn:8080/svc/hello-openssl"},
	}

	for name, tc := range tests {
		t.Run(name, func(t *testing.T) { // 使用t.Run()执行子测试
			resp, err := client.Get(tc.url)
			if err != nil {
				fmt.Println("Get error:", err)
				return
			}
			defer resp.Body.Close()

			body, err := ioutil.ReadAll(resp.Body)
			fmt.Println(string(body))
		})
	}
}

跟普通的客户端相比,需要做的额外操作:

  • 创建认证池
  • 读取根认证,或者其他证书(这些证书是用来验证服务器端证书的)
  • 将证书加载到认证池里

在这里插入图片描述

在这里插入图片描述

在/etc/hosts里设置域名,进行测试
在这里插入图片描述

查看服务器端的证书里,支持哪些域名呢?

openssl x509 -in server.crt -noout -text 

在这里插入图片描述

一次性测试所有测试用例

在这里插入图片描述

仅测试某个测试用例

在这里插入图片描述

4.1.2、使用curl方式验证服务器端证书

在这里插入图片描述

4.1.3、使用Postman方式验证服务器端证书

当前postman版本:(Mac环境下)
在这里插入图片描述

先测试一下,不添加根证书的情况:

在这里插入图片描述

添加ca.crt证书,再测试

如何添加ca.crt证书?
在这里插入图片描述

在这里插入图片描述

开始测试
在这里插入图片描述

4.2、客户端不用验证服务器端证书

4.2.1、代码方式不验证

package main

import (
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: true, // 不用校验服务器证书
		},
	}

	client := &http.Client{Transport: tr}
	resp, err := client.Get("https://www.golang-server.cn:8080/svc/hello-openssl")
	if err != nil {
		fmt.Println("Get error:", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	fmt.Println(string(body))
}

4.2.2、curl方式不验证

在这里插入图片描述

4.2.3、postman方式不验证

4.2.3.1、方式一:可以直接发起请求,出现下图时,点击Disable SSL Verification即可

在这里插入图片描述

4.2.3.2、方式二:发起请求前,先修改参数,禁止验证服务器端证书功能

在这里插入图片描述

4.2.3.3、此时,如果想恢复验证,如何处理?

在这里插入图片描述

在这里插入图片描述

下一篇文章
  https双向认证介绍

本文含有隐藏内容,请 开通VIP 后查看