Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo)

Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo),第1张

概述简介小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。系列云原生API网关,gRPC-GatewayV2初探业务流程官方开发接入文档初始化项目开发环境为少的本地开发环境go version# go version go1.14.14 darwin/amd64protoc 

简介

小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。

系列云原生 API 网关,gRPC-Gateway V2 初探业务流程

官方开发接入文档初始化项目开发环境

为少 的本地开发环境

go version# go version go1.14.14 darwin/amd64protoc --version# libprotoc 3.15.7protoc-gen-go --version# protoc-gen-go v1.26.0protoc-gen-go-grpc --version# protoc-gen-go-grpc 1.1.0protoc-gen-grpc-gateway --version
初始代码结构

使用 go mod init server 初始化 Go 项目,这里(demo)我直接采用 server 作为当前 module 名字。

go-grpc-gateway-v2-microservice

├── auth // 鉴权微服务│   ├── API│   ├── ├── gen│   ├── ├── ├── v1 // 生成的代码将放到这里,v1 表示第一个 API 版本│   │   ├── auth.proto│   │   └── auth.yaml│   ├── auth│   │   └── auth.go // service 的具体实现│   ├── wechat │   └── main.go // 鉴权 gRPC server├── gateway // gRPC-Gateway,反向代理到各个 gRPC Server│   └── main.go├── gen.sh // 根据 `auth.proto` 生成代码的命令└── go.mod
领域(auth.proto)定义
Syntax = "proto3";package auth.v1;option go_package="server/auth/API/gen/v1;authpb";// 客户端发送一个 codemessage LoginRequest {    string code = 1;}// 开发者服务器返回一个自定义登录态(token)message LoginResponse {    string access_token = 1;    int32 expires_in = 2; // 按 oauth2 约定走}service AuthService {    rpc Login (LoginRequest) returns (LoginResponse);}
使用 gRPC-Gateway 暴露 RESTful JsON APIauth.yaml 定义
type: Google.API.Serviceconfig_version: 3http:  rules:  - selector: auth.v1.AuthService.Login    post: /v1/auth/login    body: "*"
根据配置生成代码使用 gen.sh 生成 gRPC-Gateway 相关代码
PROTO_PATH=./auth/APIGO_OUT_PATH=./auth/API/gen/v1protoc -I=$PROTO_PATH --go_out=paths=source_relative:$GO_OUT_PATH auth.protoprotoc -I=$PROTO_PATH --go-grpc_out=paths=source_relative:$GO_OUT_PATH auth.protoprotoc -I=$PROTO_PATH --grpc-gateway_out=paths=source_relative,grpc_API_configuration=$PROTO_PATH/auth.yaml:$GO_OUT_PATH auth.proto

运行:

sh gen.sh

成功后,会生成 auth.pb.goauth_grpc.pb.goauth.pb.gw.go 文件,代码结构如下:

├── auth│   ├── API│   ├── ├── gen│   ├── ├── ├── v1│   ├── ├── ├── ├── auth.pb.go // 生成的 golang 相关的 protobuf 代码│   ├── ├── ├── ├── auth_grpc.pb.go  // 生成 golang 相关的 gRPC Server 代码│   ├── ├── ├── ├── auth.pb.gw.go // 生成 golang 相关的 gRPC-Gateway 代码│   │   ├── auth.proto│   │   └── auth.yaml│   ├── auth│   │   └── auth.go│   ├── wechat │   └── main.go├── gateway│   └── main.go├── gen.sh└── go.mod

整理一下包:

go mod tIDy
初步实现 Auth gRPC Service Server实现 AuthServiceServer 接口

我们查看生成 auth_grpc.pb.go 代码,找到 AuthServiceServer 定义:

……// AuthServiceServer is the server API for AuthService service.// All implementations must embed UnimplementedAuthServiceServer// for forward compatibilitytype AuthServiceServer interface {	Login(context.Context, *LoginRequest) (*LoginResponse, error)	mustembedUnimplementedAuthServiceServer()}……

我们在 auth/auth/auth.go 进行它的实现:

关键代码解读:

// 定义 Service 结构体type Service struct {	Logger         *zap.Logger	OpenIDResolver OpenIDResolver	authpb.UnimplementedAuthServiceServer}// 这里作为使用者来说做一个抽象// 定义与微信第三方服务器通信的接口type OpenIDResolver interface {	Resolve(code string) (string, error)}// 具体的方法实现func (s *Service) Login(c context.Context, req *authpb.LoginRequest) (*authpb.LoginResponse, error) {	s.Logger.Info("received code",		zap.String("code", req.Code))	// 调用微信服务器,拿到用户的唯一标识 openID		openID, err := s.OpenIDResolver.Resolve(req.Code)	if err != nil {		return nil, status.Errorf(codes.Unavailable,			"cannot resolve openID: %v", err)	}	// 调试代码,先这样写	return &authpb.LoginResponse{		Accesstoken: "token for open ID " + openID,		ExpiresIn:   7200,	}, nil}

这里有一个非常重要的编程理念,用好可以事半功倍。接口定义由使用者定义而不是实现者,如这里的 OpenIDResolver 接口。

实现 OpenIDResolver 接口

这里用到了社区的一个第三方库,这里主要用来完成开发者服务器向微信服务器换取 用户唯一标识 OpenID 、 用户在微信开放平台帐号下的唯一标识 UnionID(若当前小程序已绑定到微信开放平台帐号) 和 会话密钥 session_key
当然,不用这个库,自己写也挺简单。

go get -u github.com/medivhzhan/weapp/v2

我们在 auth/wechat/wechat.go 进行它的实现:

关键代码解读:

// 相同的 Service 实现套路再来一遍// AppID & AppSecret 要可配置,是从外面传进来的type Service struct {	AppID     string	AppSecret string}func (s *Service) Resolve(code string) (string, error) {	resp, err := weapp.Login(s.AppID, s.AppSecret, code)	if err != nil {		return "", fmt.Errorf("weapp.Login: %v", err)	}	if err = resp.GetResponseError(); err != nil {		return "", fmt.Errorf("weapp response error: %v", err)	}	return resp.OpenID, nil}
配置 Auth Service gRPC Server

auth/main.go

func main() {	logger, err := zap.NewDevelopment()	if err != nil {		log.Fatalf("cannot create logger: %v", err)	}    // 配置服务器监听端口	lis, err := net.Listen("tcp", ":8081")	if err != nil {		logger.Fatal("cannot Listen", zap.Error(err))	}        // 新建 gRPC server	s := grpc.NewServer()	// 配置具体 Service	authpb.RegisterauthServiceServer(s, &auth.Service{		OpenIDResolver: &wechat.Service{			AppID:     "your-app-id",			AppSecret: "your-app-secret",		},		Logger: logger,	})	// 对外开始服务	err = s.Serve(lis)	if err != nil {	    logger.Fatal("cannot server", zap.Error(err))   	}}
初步实现 API Gateway

gateway/main.go

// 创建一个可取消的上下文(如:请求发到一半可随时取消)c := context.Background()c, cancel := context.WithCancel(c)defer cancel()mux := runtime.NewServeMux(runtime.WithMarshalerOption(	runtime.MIMEWildcard,	&runtime.JsONPb{		MarshalOptions: protoJson.MarshalOptions{			UseEnumNumbers: true, // 枚举字段的值使用数字			UseProtonames:  true, 			// 传给 clIEnts 的 Json key 使用下划线 `_`			// Accesstoken string `protobuf:"bytes,1,opt,name=access_token,Json=accesstoken,proto3" Json:"access_token,omitempty"`			// 这里说明应使用 access_token		},		UnmarshalOptions: protoJson.UnmarshalOptions{			discardUnkNown: true, // 忽略 clIEnt 发送的不存在的 poroto 字段		},	},))err := authpb.RegisterauthServiceHandlerFromEndpoint(	c,	mux,	"localhost:8081",	[]grpc.DialOption{grpc.WithInsecure()},)if err != nil {	log.Fatalf("cannot register auth service: %v", err)}err = http.ListenAndServe(":8080", mux)if err != nil {	log.Fatalf("cannot Listen and server: %v", err)}
测试
// 发送 res.code 到后台换取 openID, sessionKey, unionIDwx.request({  url: "http://localhost:8080/v1/auth/login",  method: "POST",  data: { code: res.code },  success: console.log,  fail: console.error,})

RefsDemo: go-grpc-gateway-v2-microservicegRPC-GatewaygRPC-Gateway Docs
我是为少微信:uuhells123公众号:***下午茶加我微信(互相学习交流),关注公众号(获取更多学习资料~)
总结

以上是内存溢出为你收集整理的Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo)全部内容,希望文章能够帮你解决Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1238637.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存