IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> Go微服务五 Go - gRPC 中的TLS认证 -> 正文阅读

[网络协议]Go微服务五 Go - gRPC 中的TLS认证

创作不易感谢支持。
一条主写Go和PHP的小菜鸟。平常有时间喜欢自己写点东西,如有不对的地方,欢迎大佬指点。 个人博客:太阳上的雨天 地址:http://blog.caixiaoxin.cn 善于分享,希望有助他人. 非常感谢各位大佬的关注和支持

介绍

在上一篇中简单介绍了 在go中gRPC的使用,但是无签名的认证。这一篇简单介绍生成cert进行TLS认证的调用

代码较上一篇改动不大。包含使用openssl生成ca证书

证书生成流程

  1. 新增ca.conf
[ req ]
default_bits       = 4096
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName                 = CN
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = ZheJiang
localityName                = Locality Name (eg, city)
localityName_default        = HangZhou
organizationName            = Organization Name (eg, company)
organizationName_default    = cc
commonName                  = cc.io
commonName_max              = 64
commonName_default          = cc.io
  1. 生成CA私钥
openssl genrsa -out ca.key 4096
  1. 生成CA证书
openssl req -new -x509 -days 365 -subj "/C=CN/L=HangZhou/O=cc/CN=cc.io" -key ca.key -out ca.crt -config ca.conf
  1. 生成服务端证书
[ req ]
default_bits       = 2048
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
countryName                 = Country Name (2 letter code)
countryName_default         = CN
stateOrProvinceName         = State or Province Name (full name)
stateOrProvinceName_default = ZheJiang
localityName                = Locality Name (eg, city)
localityName_default        = HangZhou
organizationName            = Organization Name (eg, company)
organizationName_default    = cc
commonName                  = CommonName (e.g. server FQDN or YOUR name)
commonName_max              = 64
commonName_default          = cc.io  (自定义,客户端需要此字段做匹配)
[ req_ext ]
subjectAltName = @alt_names
[alt_names]
DNS.1   = cc.io
IP      = 127.0.0.1
  1. 生成公钥
openssl genrsa -out server.key 2048
  1. 生成CSR
openssl req -new  -subj "/C=CN/L=HangZhou/O=cc/CN=cc.io" -key server.key -out server.csr -config \ server.conf
  1. 基于CA签发证书
openssl x509 -req -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -in server.csr -out \ server.crt -extensions req_ext -extfile server.conf
  1. 生成客户端证书
openssl genrsa -out client.key 2048
  1. 生成CSR
openssl req -new -subj "/C=CN/L=HangZhou/O=cc/CN=cc.io" -key client.key -out client.csr
  1. 基于CA签发证书
openssl x509 -req -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -days 365 -in client.csr -out \ client.crt

image-20220305141413219

  1. 在grpcserver项目和grpcclient项目下分别创建keys目录,将server和client的证书和ca的证书复制进去

    代码实现:

    服务端:

    package main
    
    import (
    	"crypto/tls"
    	"crypto/x509"
    	"fmt"
    	"io/ioutil"
    	"net"
    
    	"google.golang.org/grpc/credentials"
    
    	"google.golang.org/grpc"
    	"gorpc.jtthink.co/services"
    )
    
    func main() {
    
    	// 公钥中读取解析公钥、私钥
    	cert, err := tls.LoadX509KeyPair("keys/server.crt", "keys/server.key")
    	if err != nil {
    		fmt.Println("LoadX509KeyPair error", err)
    		return
    	}
    
    	// 创建证书池
    	certPool := x509.NewCertPool()
    	ca, err := ioutil.ReadFile("keys/ca.crt")
    	if err != nil {
    		fmt.Println("read ca pem error ", err)
    		return
    	}
    	
    	// 解析证书
    	if ok := certPool.AppendCertsFromPEM(ca); !ok {
    		fmt.Println("AppendCertsFromPEM error ")
    		return
    	}
    	
    	cred := credentials.NewTLS(&tls.Config{
    		Certificates: []tls.Certificate{cert},
    		ClientAuth:   tls.RequireAndVerifyClientCert,
    		ClientCAs:    certPool,
    	})
    
    	rpcServer := grpc.NewServer(grpc.Creds(cred))
    
    	services.RegisterProdServiceServer(rpcServer, new(services.ProdService))
    
    	listen, _ := net.Listen("tcp", ":8082")
    
    	fmt.Println("服务启动成功...")
    	rpcServer.Serve(listen)
    }
    
    

    go run server.go

    结果:

    ? go run server.go
    服务启动成功...
    
    
    
    

    客户端代码实现

    package main
    
    import (
    	"context"
    	"crypto/tls"
    	"crypto/x509"
    	"fmt"
    	"io/ioutil"
    	"log"
    
    	"google.golang.org/grpc/credentials"
    
    	"grpccli/services"
    
    	"google.golang.org/grpc"
    )
    
    func main() {
    	pair, err := tls.LoadX509KeyPair("keys/client.crt", "keys/client.key")
    	if err != nil {
    		fmt.Println("LoadX509KeyPair error ", err)
    		return
    	}
    	certPool := x509.NewCertPool()
    	ca, err := ioutil.ReadFile("keys/ca.crt")
    	if err != nil {
    		fmt.Println("ReadFile ca.crt error ", err)
    		return
    	}
    
    	if ok := certPool.AppendCertsFromPEM(ca); !ok {
    		fmt.Println("certPool.AppendCertsFromPEM error ")
    		return
    	}
    
    	cred := credentials.NewTLS(&tls.Config{
    		Certificates: []tls.Certificate{pair},
    		ServerName:   "cc.io",
    		RootCAs:      certPool,
    	})
    
    	conn, err := grpc.Dial(":8082", grpc.WithTransportCredentials(cred))
    	if err != nil {
    		log.Fatal(err)
    	}
    	defer conn.Close()
    
    	client := services.NewProdServiceClient(conn)
     
    	prodRes, err := client.GetProdStock(context.Background(), &services.ProdRequest{
    		ProdId: 10,
    	})
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	fmt.Println(prodRes.ProdStock)
    }
    
    
    

    go run client.go

    结果:

    ? go run client.go                              
    20
    
    

上面代码是基于tcp实现的服务端,基于http实现如下

server.go

package main

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

	"google.golang.org/grpc/credentials"

	"google.golang.org/grpc"
	"gorpc.jtthink.co/services"
)

func main() {

	// 公钥中读取解析公钥、私钥
	cert, err := tls.LoadX509KeyPair("keys/server.crt", "keys/server.key")
	if err != nil {
		fmt.Println("LoadX509KeyPair error", err)
		return
	}

	// 创建证书池
	certPool := x509.NewCertPool()
	ca, err := ioutil.ReadFile("keys/ca.crt")
	if err != nil {
		fmt.Println("read ca pem error ", err)
		return
	}

	// 解析证书
	if ok := certPool.AppendCertsFromPEM(ca); !ok {
		fmt.Println("AppendCertsFromPEM error ")
		return
	}

	cred := credentials.NewTLS(&tls.Config{
		Certificates: []tls.Certificate{cert},
		ClientAuth:   tls.RequireAndVerifyClientCert,
		ClientCAs:    certPool,
	})

	rpcServer := grpc.NewServer(grpc.Creds(cred))

	services.RegisterProdServiceServer(rpcServer, new(services.ProdService))

	//listen, _ := net.Listen("tcp", ":8082")

	mux := http.NewServeMux()
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		fmt.Println(r.Proto)
		fmt.Println(r.Header)
		fmt.Println(r)
		rpcServer.ServeHTTP(w, r)
	})

	httpServer := &http.Server{
		Addr:    ":8083",
		Handler: mux,
	}

	httpServer.ListenAndServeTLS("keys/server.crt", "keys/server.key")

	//fmt.Println("服务启动成功...")
	//rpcServer.Serve(listen)
}

client.go代码不变

执行

go run server.go
go run client.go

结果

? go run client.go
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 21:30:49  更:2022-03-21 21:31:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:52:32-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码