写点什么

微服务从代码到 k8s 部署应有尽有系列(三、鉴权)

作者:万俊峰Kevin
  • 2022 年 2 月 25 日
  • 本文字数:2352 字

    阅读完需:约 8 分钟

我们用一个系列来讲解从需求到上线、从代码到 k8s 部署、从日志到监控等各个方面的微服务完整实践。

整个项目使用了 go-zero 开发的微服务,基本包含了 go-zero 以及相关 go-zero 作者开发的一些中间件,所用到的技术栈基本是 go-zero 项目组的自研组件,基本是 go-zero 全家桶了。

实战项目地址:https://github.com/Mikaelemmmm/go-zero-looklook

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 earlierGO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero/tools/goctl@latest
# for Go 1.16 and laterGOPROXY=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

链接:https://github.com/protocolbuffers/protobuf/releases

直接找到对应平台的 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=././pbgoctl: 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-gogoctl 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 -> 用户请求的资源

项目地址

https://github.com/zeromicro/go-zero

欢迎使用 go-zerostar 支持我们!

微信交流群

关注『微服务实践』公众号并点击 交流群 获取社区群二维码。

发布于: 刚刚阅读数: 2
用户头像

保持简单 2017.10.24 加入

go-zero作者

评论

发布
暂无评论
微服务从代码到k8s部署应有尽有系列(三、鉴权)