gRPC with JWT
1.iota简介2.go generate命令简介3.golang uuid库介绍4.gRPC基本教程5.protolator简介6.Govulncheck v1.0.0 发布了!7.每日一库:GORM简介8.Go泛型简介9.Go 1.21发布!10.Golang zip压缩文件读写操作11.本地搭建playground12.zap自定义日志级别13.Gorm日志设置14.gin启动https支持15.Go Plugin介绍16.Golang漏洞管理17.可以丢掉123456了18.如何优雅地退出程序19.PGO前瞻20.go多版本管理21.openAI发布v0.2.0了22.Gin中间件开发23.Fabric区块链浏览器(1)24.每日一库:Memcache25.protojson简介26.每日一库:gosec27.Fabric区块链浏览器(2)28.每日一库:fsnotify简介
29.gRPC with JWT
30.embed简介31.Fabric区块链浏览器(3)32.每日一库:pprof简介33.go 1.21:cmp34.完全可复制、经过验证的 Go 工具链35.PGO in Go 1.2136.Fabric 2.x 智能合约开发记录37.为不断增长的Go生态系统扩展gopls38.每日一库:lumberjack -- 日志轮换和管理39.2023-04-26-微信安全模式下消息解析40.WASI support in Go41.每日一库:Prometheus42.如何实现流量控制和熔断降级?43.消息队列 - RabbitMQ44.Go 1.22 中的 For 循环45.设计模式之单例模式46.每日一库:使用Viper处理Go应用程序的配置47.使用 gopkg.in/yaml.v3 解析 YAML 数据48.在Go中如何实现并发49.解析类型参数50.设计模式之工厂模式51.每日一库:cobra 简介52.slices in Go 1.2153.go defer简介54.slice简介55.Golang Map底层实现简述56.Go 如何实现多态57.查找数组中第K大的元素58.go中的内存逃逸59.数组 vs. 切片60.队列(Queue):先进先出(FIFO)的数据结构61.go 中如何实现定时任务62.go 中的循环依赖63.Go中字符串处理:fmt.Sprintf与string.Builder的比较64.理解Go中的零值65.go 上下文:context.Context66.go中异常处理流程67.Go实现网络代理68.Why gRPC ?69.Go:条件控制语句70.Go 获取 IP 地址71.Golang并发控制方式有几种?72.Golang面试:泛型73.LRU算法简介74.MRU算法实现75.ARC算法实现76.Go语言中的交互式CLI开发:survey库简介77.C如何调用Go在 gRPC 中使用 JWT(JSON Web Tokens)进行身份验证是一种常见的做法,它可以帮助你确保请求方的身份和权限。下面是一种使用 gRPC 和 JWT 进行身份验证的步骤:
- 生成和签发 JWT: 在用户登录成功后,你需要生成一个 JWT 并将其签发给用户。JWT 中可以包含一些有关用户身份、角色、权限等的信息。
- 在 gRPC 的上下文中传递 JWT: 当客户端发送 gRPC 请求时,可以将 JWT 放置在 gRPC 请求的元数据(Metadata)中,作为请求的一部分。这样,服务器端就可以获取 JWT 并对其进行验证。
- 服务器端验证 JWT: 在 gRPC 服务端,你需要编写代码来验证接收到的 JWT。这通常涉及到验证 JWT 的签名是否有效,以及检查其中的身份信息和权限等。
- 决策和授权: 根据验证后的 JWT 信息,你可以决定是否允许用户继续访问请求的资源。这可能涉及到一些授权策略和业务逻辑。
以下是一个简单的示例,展示如何在 gRPC 中使用 JWT 进行身份验证:
proto文件
内容如下:
syntax = "proto3"; package chaincode.pb; option go_package = "./;pb"; message HelloRequest { string name = 1; } message HelloResponse { string reply = 2; } service SayHi { rpc Hi(HelloRequest) returns (HelloResponse); }
通过下面的命令生成相关的文件:
$ protoc --go_out=./ --go-grpc_out=./ example.proto $ tree . ├── example_grpc.pb.go ├── example.pb.go └── example.proto 0 directories, 3 files
server端
跟 client 端约定内容如下:
- token有效期为半小时
- iss使用gRPC token
- sub使用gRPC example server
代码如下:
package main import ( "chaincode/pb" "context" "fmt" "net" "time" "github.com/golang-jwt/jwt/v5" "github.com/pkg/errors" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) var testKey = "testKey" type HiService struct { pb.UnimplementedSayHiServer } func verifyToken(tokenString string) error { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { return []byte(testKey), nil }) if err != nil { return errors.Wrap(err, "init token parser error") } if !token.Valid { return errors.New("invalid token") } claims, ok := token.Claims.(jwt.MapClaims) if !ok { return errors.New("invalid claims") } exp, err := claims.GetExpirationTime() if err != nil { return errors.Wrap(err, "GetExpirationTime from token error") } now := time.Now() if now.Sub(exp.Time) > 0 { return errors.New("the token expires") } if claims["sub"] != "gRPC example server" { return errors.New("invalid sub") } if claims["iss"] != "gRPC token" { return errors.New("invalid iss") } return nil } func (s *HiService) Hi(ctx context.Context, req *pb.HelloRequest) (*pb.HelloResponse, error) { md, ok := metadata.FromIncomingContext(ctx) if !ok { return nil, errors.New("token信息获取失败") } token := md.Get("Authorization")[0] if err := verifyToken(token); err != nil { return nil, errors.Wrap(err, "token验证失败") } return &pb.HelloResponse{Reply: "hello " + req.Name}, nil } func main() { // 创建grpc服务示例 sv := grpc.NewServer() // 注册我们的服务 pb.RegisterSayHiServer(sv, new(HiService)) // 绑定端口,提供服务 lis, err := net.Listen("tcp", ":50001") if err != nil { panic(err) } // 启动服务 fmt.Println("liston on: 50001") sv.Serve(lis) }
$ go run main.go liston on: 50001
client
代码如下:
package main import ( "chaincode/pb" "context" "fmt" "time" "github.com/golang-jwt/jwt/v5" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" ) var testKey = "testKey" func genToken() (string, error) { claims := jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(time.Now().Add(30 * time.Minute)), Issuer: "gRPC token", Subject: "gRPC example client", } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) return token.SignedString([]byte(testKey)) } type TokeAuth struct { Token string } func (t *TokeAuth) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { return map[string]string{ "Authorization": t.Token, }, nil } func (t *TokeAuth) RequireTransportSecurity() bool { return false } func main() { token, err := genToken() if err != nil { panic(err) } conn, err := grpc.Dial("localhost:50001", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithPerRPCCredentials(&TokeAuth{Token: token})) if err != nil { panic(err) } defer conn.Close() client := pb.NewSayHiClient(conn) resp, err := client.Hi(context.Background(), &pb.HelloRequest{Name: "Wang"}) if err != nil { panic(err) } fmt.Println(resp.String()) }
现在我们先将 client 端生成 token 的sub
设置为 gRPC example client
,执行
$ go run main.go panic: rpc error: code = Unknown desc = token验证失败: invalid sub goroutine 1 [running]: main.main() /root/go/src/example/client/main.go:55 +0x2f2 exit status 2
再将 client 端生成 token 的sub
设置为 gRPC example server
,执行
$ go run main.go reply:"hello Wang"
以上示例是一个简单的代码示例,实际上还需要处理错误、安全性和其他细节。

声明:本作品采用署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)进行许可,使用时请注明出处。
Author: mengbin
blog: mengbin
Github: mengbin92
cnblogs: 恋水无意
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程