grpc之golang请求带token
  Adknp2DJyaqB 2023年11月13日 32 0

在前面 grpc之golang的简单使用 增加一个请求权限验证

  1. 在proto下面新建token目录,添加token.proto文件
syntax = "proto3";
//option java_package = "com.colobu.rpctest";
package token;
option go_package = "/";
// The greeting service definition.
service Token {
  // Sends a greeting
  rpc GetToken (UserRequest) returns (TokenData) {}
  rpc TestToken (TokenData) returns (TestTokenResponse){}
}

message UserRequest {
  string userName = 1;
  string passWord = 2;
}

message TokenData {
  string accessToken = 1;
}

message TestTokenResponse {
  bool ispass = 1;
  string message = 2;
}

然后在当前目录生成文件

protoc --go_out=. --go-grpc_out=. token.proto
  1. 在server目录下面新建token.go

package server

import (
	"context"
	"encoding/json"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/status"
	token "rpc/proto/token"
	"rpc/tool"
)

type Token struct {
	token.UnimplementedTokenServer
}

// 生成token
func (s *Token) GetToken(ctx context.Context, in *token.UserRequest) (*token.TokenData, error) {
	md, _ := metadata.FromIncomingContext(ctx)
	var name, passwrod string
	if value, ok := md["username"]; ok {
		name = value[0]
	}
	if value, ok := md["password"]; ok {
		passwrod = value[0]
	}
	var usrInfo token.UserRequest
	usrInfo.UserName = name
	usrInfo.PassWord = passwrod
	userjson, _ := json.Marshal(usrInfo)
	tokenStr := tool.TokenEnCode(string(userjson))
	return &token.TokenData{AccessToken: tokenStr}, nil
}

// 验证token
func (t *Token) Check(ctx context.Context) error {
	// 从上下文章获取元数据
	md, ok := metadata.FromIncomingContext(ctx)

	if !ok {
		return status.Errorf(codes.Unauthenticated, "获取token失败")
	}
	var str string
	if value, ok := md["accesstoken"]; ok {
		str = value[0]
	}
	tokenStr := tool.TokenDeCode(str)

	var user token.UserRequest
	json.Unmarshal([]byte(tokenStr), &user)

	if user.UserName != "wms" || user.PassWord != "123456" {
		return status.Errorf(codes.Unauthenticated, "Token无效")
	}
	return nil
}

方法中的用户名密码没有保存到数据库,只是做简单测试。 3. 根目录下面建立tool文件夹,放加密方法 加密库用的是github.com/golang-module/dongle

go get github.com/golang-module/dongle
package tool

import "github.com/golang-module/dongle"

func TokenEnCode(str string) string {
	return dongle.Encode.FromString(dongle.Encode.FromString(string(str)).ByBase64().ToString()).ByHex().ToString()
}

func TokenDeCode(str string) string {
	return dongle.Decode.FromString(dongle.Decode.FromString(str).ByHex().ToString()).ByBase64().ToString()
}
  1. 在server文件夹下面的carrier文件中的rpc方法增加token验证
func (carrier *Carrier) GetCarrier(ctx context.Context, in *rca.CarrierRequest) (*rca.CarrierMsg, error) {
	// 检测Token是否有效
	if err := tToken.Check(ctx); err != nil {
		return nil, err
	}
	return &rca.CarrierMsg{Id:1,Name:"test"}, nil
}

func (carrier *Carrier) GetCarriers(ctx context.Context, in *rca.CarriersRequest) (*rca.CarriersReply, error) {
	// 检测Token是否有效
	if err := tToken.Check(ctx); err != nil {
		return nil, err
	}
	return &rca.CarriersReply{Page:1,PageSize:10,CarrierInfo:nil}, nil
}
  1. 然后启动server
go run server.go
  1. 客户端请求metadata增加 accessToken 字段
package main

import (
	"context"
	"flag"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials/insecure"
	"log"
	rca "rpc/proto/carrier"
	"time"
)

type CAuth struct {
}

func (c CAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
	//TODO implement me
	return map[string]string{
		"accessToken": "65794a3163325679546d46745a534936496e647463794973496e426863334e5862334a6b496a6f694d54497a4e445532496e303d",
	}, nil
}

func (c CAuth) RequireTransportSecurity() bool {
	return false
}
func main() {
	var addr = flag.String("addr", "ip:50051", "the address to connect to")
	flag.Parse()
	var opts []grpc.DialOption
	opts = append(opts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	opts = append(opts, grpc.WithPerRPCCredentials(new(CAuth)))
	conn, err := grpc.Dial(*addr, opts...)
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := rca.NewCarrierClient(conn)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	r1, err := c.GetCarrier(ctx, &rca.CarrierRequest{Name: "sdfsdfsdf"})
	if err != nil {
		log.Fatalf("could not greet: %v", err)
	}
	log.Printf("Carrier: %s", r1.GetName())
}

  1. 或者用postman请求在metadata添加 accessToken image 如果没有带token会拦截请求 image
【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月13日 0

暂无评论

Adknp2DJyaqB