gRPC with JWT
在 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: 恋水无意
gRPC with JWT的更多相关文章
- Akka-CQRS(16)- gRPC用JWT进行权限管理
前面谈过gRPC的SSL/TLS安全机制,发现设置过程比较复杂:比如证书签名:需要服务端.客户端两头都设置等.想想实际上用JWT会更加便捷,而且更安全和功能强大,因为除JWT的加密签名之外还可以把私密 ...
- gRPC四种模式、认证和授权实战演示,必赞~~~
前言 上一篇对gRPC进行简单介绍,并通过示例体验了一下开发过程.接下来说说实际开发常用功能,如:gRPC的四种模式.gRPC集成JWT做认证和授权等. 正文 1. gRPC四种模式服务 以下案例演示 ...
- 编写一个go gRPC的服务
前置条件: 获取 gRPC-go 源码 $ go get google.golang.org/grpc 简单例子的源码位置: $ cd $GOPATH/src/google.golang.org/gr ...
- grpc编译错误解决
berli@berli-VirtualBox:~/grpc$ make [MAKE] Generating cache.mk [C] Compiling src/core/lib/s ...
- ASP.NET Core 3.0 gRPC 身份认证和授权
一.开头聊骚 本文算是对于 ASP.NET Core 3.0 gRPC 研究性学习的最后一篇了,以后在实际使用中,可能会发一些经验之文.本文主要讲 ASP.NET Core 本身的认证授权和gRPC接 ...
- gRPC asp.net core自定义策略认证
在GitHub上有个项目,本来是作为自己研究学习.net core的Demo,没想到很多同学在看,还给了很多星,所以觉得应该升成3.0,整理一下,写成博分享给学习.net core的同学们. 项目名称 ...
- 浅议Grpc传输机制和WCF中的回调机制的代码迁移
浅议Grpc传输机制和WCF中的回调机制的代码迁移 一.引子 如您所知,gRPC是目前比较常见的rpc框架,可以方便的作为服务与服务之间的通信基础设施,为构建微服务体系提供非常强有力的支持. 而基于. ...
- Go gRPC进阶-go-grpc-middleware使用(八)
前言 上篇介绍了gRPC中TLS认证和自定义方法认证,最后还简单介绍了gRPC拦截器的使用.gRPC自身只能设置一个拦截器,所有逻辑都写一起会比较乱.本篇简单介绍go-grpc-middleware的 ...
- akka-grpc - 基于akka-http和akka-streams的scala gRPC开发工具
关于grpc,在前面的scalaPB讨论里已经做了详细的介绍:google gRPC是一种全新的RPC框架,在开源前一直是google内部使用的集成工具.gRPC支持通过http/2实现protobu ...
- 跟我一起学Go系列:Go gRPC 安全认证方式-Token和自定义认证
Go gRPC 系列: 跟我一起学Go系列:gRPC安全认证机制-SSL/TLS认证 跟我一起学 Go 系列:gRPC 拦截器使用 跟我一起学 Go 系列:gRPC 入门必备 接上一篇继续讲 gRPC ...
随机推荐
- 配置阿里云docker镜像加速
配置好后 重新加载一下 daemon [root@centos-linux jimmy]# systemctl daemon-reload [root@centos-linux jimmy]# sys ...
- selenium多标签,多表单切换
Selenium多标签之间的切换 多标签之间的切换 有的时候点击一个链接,新页面并非由当前页面跳转过去,而是新打开一个页面打开,这种情况下,计算机需要识别多标签或窗口的情况 获取所有窗口的句柄 han ...
- 详解 SSL(三):SSL 证书该如何选择?
在上一篇< 详解 SSL(二):SSL 证书对网站的好处>中,我们知道了在网站部署 SSL 证书后,不管是对网站本身还是对网站的用户都能够带来许多好处.那么随着 HTTPS 的普及,市面上 ...
- 精细化边缘安全防护:如何防止CDN域名被恶意刷量?
越是数字化时代,越要做好基建"安全"的顶层设计 随着消费及产业互联网的不断发展,数字化将实现全场景覆盖,人类的生活和生产方式也随之不断改变. 内容分发网络CDN(Content D ...
- POJ - 1611 : The Suspects (普通并查集)
思路: 模板题,一步一步加入集合,最后判断有多少人跟0在同一个集合就行了. #include<iostream> #include<cstdio> using namespac ...
- 写SAE评测,获 Airpods 2大奖【集结令】!
Serverless 应用引擎 SAE 开启测评有奖!名额有限,先到先得! Serverless应用引擎SAE是一款极简易用.自适应弹性的容器化应用平台.现面向所有用户发出诚挚邀请,参与一分钟部署在线 ...
- 活动回顾|阿里云 Serverless 技术实践营 Serverless +AI 专场
8月25日"阿里云Serverless技术实践营( Serverless + AI 专场)"北京站圆满落幕.活动受众以关注 Serverless +AI 技术的开发者.企业决策人. ...
- Serverless 奇点已来,下一个十年将驶向何方?
本文整理自 QCon 上海站 2022 丁宇(叔同)的演讲内容. 以前构建应用,需要买 ECS 实例,搭建开源软件体系然后维护它,流量大了扩容,流量小了缩容,整个过程非常复杂繁琐. 用了 Server ...
- java基础(16)--super与this
一.this简介 1.this. this() 2.静态方法无法使用 3.不省略的情况:区分局部变量与实例变量,比如set方法中用到 二.super简介 1.只能出现在实例方法或构造方法中 2. ...
- ThreadLocal应用及理解
转载请注明出处: 1. 先展示threadLocal的一个简单封装,该封装用来在不同的请求线程中解析用户参数.在请求经过过滤器时, 对用户的信息进行设置入 ThreadLocalContext 中,可 ...