1. 程式人生 > >go語言gRPC系列(二) - 為gRPC新增證書

go語言gRPC系列(二) - 為gRPC新增證書

- [1. 前言](#head1) - [2. 生成自簽證書](#head2) - [2.1 MAC生成自簽證書的教程連結: ](#head3) - [2.2 Windows生成自簽證書的教程](#head4) - [3. 改造服務端使用自簽證書](#head5) - [3.1 複製證書至程式碼下](#head6) - [3.2 改造程式碼新增證書認證](#head7) - [3.1 執行程式碼並檢視客戶端的訪問錯誤](#head8) - [4. 改造客戶端程式碼(單向認證)](#head9) - [4.1 複製公鑰給客戶端](#head10) - [4.2 改造客戶端程式碼](#head11) - [4.3 執行客戶端檢視結果](#head12) ## 1. 前言 前情回顧 > [go語言gRPC系列(一) - gRPC入門](https://www.cnblogs.com/baoshu/p/13488106.html) 之前我們演示的客戶端和服務端之間是沒有使用證書的,不是很安全。下面演示一下,服務呼叫之間加入自籤的證書驗證。 > 生產環境以網上購買的證書為準 ## 2. 生成自簽證書 ### 2.1 MAC生成自簽證書的教程連結: > https://www.jianshu.com/p/4cdd29ce424d ### 2.2 Windows生成自簽證書的教程 1. 登入如下連結 > http://slproweb.com/products/Win32OpenSSL.html 2. 下載如下的openssl工具 ![](http://pic.codepie.fun/picgo/20200814233140.png) 3. 安裝到某個目錄 4. 進入安裝目錄的bin資料夾下 5. 在所在的資料夾開啟cmd,並輸入`openssl` ![](http://pic.codepie.fun/picgo/20200814235229.png) 6. 然後再執行如下的操作, 生成私鑰檔案 - 會生成一個`server.key` ```shell genrsa -des3 -out server.key 2048 ``` ![](http://pic.codepie.fun/picgo/20200814235804.png) 7. 建立證書請求 - 會生成一個`server.csr` ```shell genrsa -des3 -out server.key 2048 ``` ![](http://pic.codepie.fun/picgo/20200815000400.png) 8. 為了演示簡單,刪除私鑰中的密碼 - 會生成一個`server_no_password.key` ``` rsa -in server.key -out server_no_password.key ``` ![](http://pic.codepie.fun/picgo/20200815000657.png) 9. 生成公鑰檔案 - 會生成`server.crt` ``` x509 -req -days 365 -in server.csr -signkey server_no_password.key -out server.crt ``` ![](http://pic.codepie.fun/picgo/20200815000942.png) ---- ## 3. 改造服務端使用自簽證書 ### 3.1 複製證書至程式碼下 在服務端的目錄下新建一個keys資料夾,並且上之前生成的`server_no_password.key`和`server.crt`複製到目錄下 ![](http://pic.codepie.fun/picgo/20200815002727.png) ### 3.2 改造程式碼新增證書認證 改造之前上一節的服務端程式碼,具體改造的部分如下標紅的部分 ![](http://pic.codepie.fun/picgo/20200815002915.png) 完整的服務端程式碼: ```go package main import ( "gomicro-quickstart/grpc_server/service" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "log" "net" ) func main() { // 1. 引用證書 tls, err := credentials.NewServerTLSFromFile("grpc_server/keys/server.crt", "grpc_server/keys/server_no_password.key") if err != nil { log.Fatal("服務端獲取證書失敗: ", err) } // 2. new一個grpc的server,並且加入證書 rpcServer := grpc.NewServer(grpc.Creds(tls)) // 3. 將剛剛我們新建的ProdService註冊進去 service.RegisterProdServiceServer(rpcServer, new(service.ProdService)) // 4. 新建一個listener,以tcp方式監聽8082埠 listener, err := net.Listen("tcp", ":8082") if err != nil { log.Fatal("服務監聽埠失敗", err) } // 5. 執行rpcServer,傳入listener _ = rpcServer.Serve(listener) } ``` ### 3.1 執行程式碼並檢視客戶端的訪問錯誤 執行`server`服務端 這時候我們同樣執行起來`client`,發現會報如下的錯,因為我們的服務端使用證書加密了 ![](http://pic.codepie.fun/picgo/20200815002334.png) ## 4. 改造客戶端程式碼(單向認證) ### 4.1 複製公鑰給客戶端 這裡為了剛入門演示方便,採用了單向認證。 1. 在客戶端程式碼下新建keys資料夾 2. 將server.crt複製到keys資料夾下 ![](http://pic.codepie.fun/picgo/20200815003547.png) ### 4.2 改造客戶端程式碼 較上一章的程式碼的改動如下圖: ![](http://pic.codepie.fun/picgo/20200815005304.png) 完整的客戶端程式碼如下: ```go package main import ( "context" "fmt" "gomicro-quickstart/grpc_client/service" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "log" ) func main() { // 1. 新增公鑰證書的引用, codepie.fun是之前生成證書的時候填寫的common name tls, err := credentials.NewClientTLSFromFile("grpc_client/keys/server.crt", "codepie.fun") if err != nil { log.Fatal("客戶端獲取證書失敗: ", err) } // 2. 新建連線,埠是服務端開放的8082埠 conn, err := grpc.Dial(":8082", grpc.WithTransportCredentials(tls)) if err != nil { log.Fatal(err) } // 退出時關閉連結 defer conn.Close() // 3. 呼叫Product.pb.go中的NewProdServiceClient方法 productServiceClient := service.NewProdServiceClient(conn) // 4. 直接像呼叫本地方法一樣呼叫GetProductStock方法 resp, err := productServiceClient.GetProductStock(context.Background(), &service.ProductRequest{ProdId: 233}) if err != nil { log.Fatal("呼叫gRPC方法錯誤: ", err) } fmt.Println("呼叫gRPC方法成功,ProdStock = ", resp.ProdStock) } ``` ### 4.3 執行客戶端檢視結果 單向認證成功,服務呼叫成功 ![](http://pic.codepie.fun/picgo/202008150054