微服務從程式碼到k8s部署應有盡有系列(三、鑑權)

kevinwan發表於2022-02-18

我們用一個系列來講解從需求到上線、從程式碼到k8s部署、從日誌到監控等各個方面的微服務完整實踐。

整個專案使用了go-zero開發的微服務,基本包含了go-zero以及相關go-zero作者開發的一些中介軟體,所用到的技術棧基本是go-zero專案組的自研元件,基本是go-zero全家桶了。

實戰專案地址:github.com/Mikaelemmmm/go-zero-loo...

1、鑑權服務

1.1 identity-api

identity主要是用來做鑑權服務的,前面我們nginx閘道器的時候有提到。在訪問一個資源的時候,nginx內部會先來identity-api中解析token,identity-api會去請求identity-rpc,所有的驗證與頒發token,統一是在identity-rpc中做的

我們會從header的Authorization中獲取token,從x-Original-Uri獲取訪問的資源路徑

  • 如果當前訪問的路由需要登陸:
    • token解析失敗:就會返回給前端http401錯誤碼;
    • token解析成功:就會將解析出來的userId放入header的x-user中返回給auth模組,auth模組會把header傳遞給對應訪問的服務(usercenter), 這樣我們在usercenter直接就可以拿到該登陸使用者的id了
  • 如果當前訪問的路由不需要登陸:
    • 前端header中傳遞了token
      • 如果token校驗失敗:返回http401;
      • 如果token校驗成功:就會將解析出來的userId放入header的x-user中返回給auth模組,auth模組會把header傳遞給對應訪問的服務(usercenter), 這樣我們在usercenter直接就可以拿到該登陸使用者的id了
    • 前端header中沒傳遞token:userid 會傳遞 0 給後端服務

urlNoAuth方法判斷當前資源是否在yml中配置可以不登陸

//當前url是否需要授權驗證
func (l *TokenLogic) urlNoAuth(path string) bool {
   for _, val := range l.svcCtx.Config.NoAuthUrls {
      if val == path {
         return true
      }
   }
   return false
}

isPass方法就是去identity-rpc校驗token,主要也是使用了go-zero的jwt的方法

1.2 identity-rpc

當我們在註冊、登陸成功時候,使用者服務會呼叫identity-rpc生成token,所以我們統一在identity-rpc中頒發、校驗token,這樣就不用每個服務都要寫個jwt去維護。

當identity-api請求進來時候,identity-api自己可以解析出來userid,但是我們要檢驗這個token是否是過期,就要去後端rpc中的redis中去進行二次校驗(當然如果你覺得這裡多一次請求,你可以把這一步放到api裡直接請求redis也可以),經過rpc的validateToken方法校驗

message ValidateTokenReq {
  int64 userId = 1;
  string token = 2;
}
message ValidateTokenResp {
  bool ok = 1;
}

rpc validateToken(ValidateTokenReq) returns(ValidateTokenResp);

校驗之前登陸、註冊等授權時候頒發出去存在redis的token是否正確、過期。

這樣api就可以返回給nginx的auth模組是否失敗,如果失敗auth會直接返回給前端http code 401(所以你們前端應該是先判斷http狀態碼>=400全部異常,再判斷業務錯誤碼) , 如果成功直接訪問後端服務了拿到資料直接返回給前端展示

2、安裝goctl 與 protoc、protoc-gen-go

【注】這個跟鑑權沒什麼關係,只是後面寫程式碼要用到,在這裡最好給安裝了

2.1 安裝goctl

# for Go 1.15 and earlier
GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero/tools/goctl@latest

# for Go 1.16 and later
GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest

驗證是否安裝成功

$ goctl --version

Goctl自定義模版template:將專案目錄下的data/goctl資料夾內容copy到 HOME 目錄的 .goctl 中,goctl在生成程式碼時候會優先根據這個模版下內容生成

$ cp -r data/goctl ~/.goctl

2.2 安裝protoc

連結:github.com/protocolbuffers/protobu...

直接找到對應平臺的protoc,我是mac intel晶片,所以直接找到 protoc-3.19.3-osx-x86_64.zip ,解壓出來後進入該目錄下的bin目錄中,將protoc直接copy到你的gopath/bin目錄下即可。

驗證是否安裝成功

$ protoc --version

2.3 安裝protoc-gen-go

$ GOPROXY=https://goproxy.cn/,direct go install google.golang.org/protobuf/cmd/protoc-gen-go@latest 

檢視$GOPATH/bin下是否有protoc-gen-go即可

【注】:如果後續在使用goctl生成程式碼時候,遇到以下問題

protoc  --proto_path=/Users/seven/Developer/goenv/go-zero-looklook/app/usercenter/cmd/rpc/pb usercenter.proto --go_out=plugins=grpc:/Users/seven/Developer/goenv/go-zero-looklook/app/usercenter/cmd/rpc --go_opt=Musercenter.proto=././pb
goctl: generation error: unsupported plugin protoc-gen-go which installed from the following source:
google.golang.org/protobuf/cmd/protoc-gen-go, 
github.com/protocolbuffers/protobuf-go/cmd/protoc-gen-go;

Please replace it by the following command, we recommend to use version before v1.3.5:
go get -u github.com/golang/protobuf/protoc-gen-go
goctl version: 1.3.0 darwin/amd64

直接執行

$ GOPROXY=https://goproxy.cn/,direct go get -u github.com/golang/protobuf/protoc-gen-go

2.4 安裝protoc-gen-go-grpc

$ GOPROXY=https://goproxy.cn/,direct go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

3、總結

總的來說,identity還算是比較簡單的,整個流程如下:

使用者發起請求資源 -> nginx閘道器->匹配到對應服務模組 -> auth模組->identity-api ->identity-rpc -> 使用者請求的資源

專案地址

github.com/zeromicro/go-zero

歡迎使用 go-zerostar 支援我們!

微信交流群

關注『微服務實踐』公眾號並點選 交流群 獲取社群群二維碼。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章