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 ...
随机推荐
- 2023年iOS App Store上架流程详解(上)
很多开发者在开发完iOS APP.进行内测后,下一步就面临上架App Store,不过也有很多同学对APP上架App Store的流程不太了解,下面我们来说一下iOS APP上架App Store ...
- 非VIP用户下载限速,原来是这么实现的
在日常工作之余,二狗子其实还是个隐藏的大触,一手素描画得出神入化,不少看过的小伙伴嗷嗷叫着求分享.为了让更多小粉丝能看到自己的作品,二狗子开发了一个提供有版权的素描稿件的下载网站. 二狗子的小网站,只 ...
- Linux 网络收包流程
哈喽大家好,我是咸鱼 我们在跟别人网上聊天的时候,有没有想过你发送的信息是怎么传到对方的电脑上的 又或者我们在上网冲浪的时候,有没有想过 HTML 页面是怎么显示在我们的电脑屏幕上的 无论是我们跟别人 ...
- POJ:3660 Cow Contest (传递闭包 + Floyd)
POJ 3660 http://poj.org/problem?id=3660 思路: 传递闭包 输入A > B,那么我们可以建立一套A ->B 的边. 然后求出传递闭包. 判断一个人是否 ...
- AtCoder Beginner Contest 204 (AB水题,C题DFS,D题位运算DP,E题BFS好题)
补题链接:Here A - Rock-paper-scissors 石头剪刀布,两方是一样的则输出该值,否则输出该值 int s[4] = {0, 1, 2}; void solve() { int ...
- nvm:npm的包管理器
NVM: npm的包管理器 其实许久前就像写这个模块了,只是之前使用后又搁置了,今天下项目时node版本不一致,才想起记录 nvm下载地址: Releases · coreybutler/nvm-wi ...
- 记一次 .NET某道闸收费系统 内存溢出分析
一:背景 1. 讲故事 前些天有位朋友找到我,说他的程序几天内存就要爆一次,不知道咋回事,找不出原因,让我帮忙看一下,这种问题分析dump是最简单粗暴了,拿到dump后接下来就是一顿分析. 二:Win ...
- 详解异步任务 | 看 Serverless Task 如何解决任务调度&可观测性中的问题
在上篇文章<解密函数计算异步任务能力之「任务的状态及生命周期管理」>中,我们介绍了任务系统的状态管理,并介绍了用户应如何根据需求,对任务状态信息进行实时的查询等操作.在本篇中我们将会进一步 ...
- 一、docker入门(概念)
系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...
- 电脑面试两道问题(python+shell)
最近面试电脑代码面试遇到两个问题,供大家参考一下一.python脚本: 手写一个函数,实现两个数相加,并使用unittest与pytest工具测试函数正确性. 1.unnitest进行测试: impo ...