From fb43bd81c99c169fee4939034d9d8ac2e8d77c98 Mon Sep 17 00:00:00 2001
From: lym <2499445495@qq.com>
Date: Fri, 26 Aug 2022 16:16:05 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0grpc=E7=89=88=E4=BA=8C?=
=?UTF-8?q?=E7=BA=A7=E4=B8=8A=E4=B8=8B=E6=96=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../sa-token-demo-grpc/client/pom.xml | 20 +++
.../client/src/main/java/com/lym/Client.java | 18 +++
.../com/lym/controller/TestController.java | 48 +++++++
.../com/lym/grpc/client/GrpcAuthService.java | 28 ++++
.../client/src/main/proto/auth.proto | 24 ++++
.../client/src/main/resources/application.yml | 18 +++
sa-token-demo/sa-token-demo-grpc/pom.xml | 122 ++++++++++++++++++
.../sa-token-demo-grpc/server/pom.xml | 20 +++
.../server/src/main/java/com/lym/Server.java | 18 +++
.../com/lym/grpc/server/GrpcAuthService.java | 37 ++++++
.../java/com/lym/service/AuthService.java | 23 ++++
.../server/src/main/proto/auth.proto | 24 ++++
.../server/src/main/resources/application.yml | 16 +++
sa-token-doc/doc/plugin/grpc-extend.md | 39 ++++++
sa-token-plugin/pom.xml | 1 +
sa-token-plugin/sa-token-context-grpc/pom.xml | 35 +++++
.../SaTokenSecondContextCreatorForGrpc.java | 20 +++
.../grpc/SaTokenSecondContextForGrpc.java | 45 +++++++
.../grpc/constants/GrpcContextConstants.java | 19 +++
.../grpc/context/SaTokenGrpcContext.java | 44 +++++++
.../SaTokenContextGrpcServerInterceptor.java | 28 ++++
.../SaTokenGrpcClientInterceptor.java | 59 +++++++++
.../SaTokenGrpcServerInterceptor.java | 42 ++++++
.../context/grpc/model/SaRequestForGrpc.java | 85 ++++++++++++
.../context/grpc/model/SaResponseForGrpc.java | 60 +++++++++
.../context/grpc/model/SaStorageForGrpc.java | 47 +++++++
.../main/resources/META-INF/spring.factories | 5 +
27 files changed, 945 insertions(+)
create mode 100644 sa-token-demo/sa-token-demo-grpc/client/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/Client.java
create mode 100644 sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/controller/TestController.java
create mode 100644 sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/grpc/client/GrpcAuthService.java
create mode 100644 sa-token-demo/sa-token-demo-grpc/client/src/main/proto/auth.proto
create mode 100644 sa-token-demo/sa-token-demo-grpc/client/src/main/resources/application.yml
create mode 100644 sa-token-demo/sa-token-demo-grpc/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-grpc/server/pom.xml
create mode 100644 sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/Server.java
create mode 100644 sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/grpc/server/GrpcAuthService.java
create mode 100644 sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/service/AuthService.java
create mode 100644 sa-token-demo/sa-token-demo-grpc/server/src/main/proto/auth.proto
create mode 100644 sa-token-demo/sa-token-demo-grpc/server/src/main/resources/application.yml
create mode 100644 sa-token-doc/doc/plugin/grpc-extend.md
create mode 100644 sa-token-plugin/sa-token-context-grpc/pom.xml
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextCreatorForGrpc.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextForGrpc.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/constants/GrpcContextConstants.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/context/SaTokenGrpcContext.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenContextGrpcServerInterceptor.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcClientInterceptor.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcServerInterceptor.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaResponseForGrpc.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaStorageForGrpc.java
create mode 100644 sa-token-plugin/sa-token-context-grpc/src/main/resources/META-INF/spring.factories
diff --git a/sa-token-demo/sa-token-demo-grpc/client/pom.xml b/sa-token-demo/sa-token-demo-grpc/client/pom.xml
new file mode 100644
index 00000000..e1799ba5
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/client/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ sa-token-demo-grpc
+ com.lym
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ client
+
+
+ 8
+ 8
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/Client.java b/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/Client.java
new file mode 100644
index 00000000..3a3d69e9
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/Client.java
@@ -0,0 +1,18 @@
+package com.lym;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 10:58
+ **/
+@SpringBootApplication
+@EnableDiscoveryClient
+public class Client {
+ public static void main(String[] args) {
+ SpringApplication.run(Client.class);
+ }
+}
diff --git a/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/controller/TestController.java b/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/controller/TestController.java
new file mode 100644
index 00000000..da36bdae
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/controller/TestController.java
@@ -0,0 +1,48 @@
+package com.lym.controller;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.lym.grpc.client.GrpcAuthService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 11:01
+ **/
+@RestController
+public class TestController {
+ @Autowired
+ private GrpcAuthService grpcAuthService;
+
+ // 客户端登录,状态带到服务端。
+ @RequestMapping("test")
+ public void test() {
+ System.out.println("登录前:" + grpcAuthService.isLogin());
+ System.out.println("登录前:" + StpUtil.isLogin());
+
+ StpUtil.login(1);
+
+ System.out.println("登录后:" + grpcAuthService.isLogin());
+ System.out.println("登录后:" + StpUtil.getTokenValue());
+ System.out.println("登录后:" + StpUtil.getLoginId());
+ }
+
+ // 服务端登录,登录状态带回客户端
+ @RequestMapping("test2")
+ public String test2() {
+ System.out.println("登录前:" + grpcAuthService.isLogin());
+ System.out.println("登录前:" + StpUtil.isLogin());
+
+ String token = grpcAuthService.login(3);
+
+ System.out.println("登录后:" + grpcAuthService.isLogin());
+ System.out.println("登录后:" + StpUtil.getTokenValue());
+ System.out.println("登录后:" + StpUtil.getLoginId());
+ assert StpUtil.getTokenValue().equals(token);
+
+ return token;
+ }
+
+}
diff --git a/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/grpc/client/GrpcAuthService.java b/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/grpc/client/GrpcAuthService.java
new file mode 100644
index 00000000..53da9e69
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/client/src/main/java/com/lym/grpc/client/GrpcAuthService.java
@@ -0,0 +1,28 @@
+package com.lym.grpc.client;
+
+import com.google.protobuf.Empty;
+import com.lym.grpc.auth.Auth;
+import com.lym.grpc.auth.AuthServiceGrpc;
+import net.devh.boot.grpc.client.inject.GrpcClient;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 11:02
+ **/
+@Service
+public class GrpcAuthService {
+ @GrpcClient("test-server")
+ private AuthServiceGrpc.AuthServiceBlockingStub grpcAuthService;
+
+ public boolean isLogin() {
+ Auth.GrpcBool resp = grpcAuthService.isLogin(Empty.getDefaultInstance());
+ return resp.getVal();
+ }
+
+ public String login(Integer id) {
+ Auth.GrpcString resp = grpcAuthService.login(Auth.GrpcInt.newBuilder().setVal(id).build());
+ return resp.getVal();
+ }
+}
diff --git a/sa-token-demo/sa-token-demo-grpc/client/src/main/proto/auth.proto b/sa-token-demo/sa-token-demo-grpc/client/src/main/proto/auth.proto
new file mode 100644
index 00000000..2113a5d4
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/client/src/main/proto/auth.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+
+package auth;
+
+option java_package = "com.lym.grpc.auth";
+import "google/protobuf/empty.proto";
+
+message GrpcBool{
+ bool val = 1;
+}
+
+message GrpcInt{
+ int32 val = 1;
+}
+
+message GrpcString{
+ string val = 1;
+}
+
+
+service AuthService{
+ rpc isLogin(google.protobuf.Empty) returns (GrpcBool);
+ rpc login(GrpcInt) returns (GrpcString);
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-grpc/client/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-grpc/client/src/main/resources/application.yml
new file mode 100644
index 00000000..d85332af
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/client/src/main/resources/application.yml
@@ -0,0 +1,18 @@
+server:
+ port: 2222
+spring:
+ application:
+ name: test-client
+ redis:
+ host: localhost
+ cloud:
+ nacos:
+ server-addr: localhost:8848
+sa-token:
+ is-read-cookie: false
+grpc:
+ server:
+ port: 2223
+ client:
+ test-server:
+ negotiation-type: PLAINTEXT
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-grpc/pom.xml b/sa-token-demo/sa-token-demo-grpc/pom.xml
new file mode 100644
index 00000000..4302cb71
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/pom.xml
@@ -0,0 +1,122 @@
+
+
+ 4.0.0
+ pom
+
+ client
+ server
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.6.3
+
+
+ com.lym
+ sa-token-demo-grpc
+ 0.0.1-SNAPSHOT
+ sa-token-demo-grpc
+ sa-token-demo-grpc
+
+
+ 8
+ 8
+ 1.8
+ UTF-8
+ UTF-8
+ UTF-8
+ 1.18.10
+ 1.30.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+ 2.7.2
+
+
+
+ cn.dev33
+ sa-token-spring-boot-starter
+ ${sa-token-version}
+
+
+ cn.dev33
+ sa-token-dao-redis-jackson
+ ${sa-token-version}
+
+
+ cn.dev33
+ sa-token-context-grpc
+ ${sa-token-version}
+
+
+
+
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-dependencies
+ 2021.0.1.0
+ pom
+ import
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ 2021.0.1
+ pom
+ import
+
+
+
+
+
+
+
+ kr.motd.maven
+ os-maven-plugin
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+
+
+ org.xolstice.maven.plugins
+ protobuf-maven-plugin
+
+ com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}
+ grpc-java
+ io.grpc:protoc-gen-grpc-java:1.12.0:exe:${os.detected.classifier}
+
+
+
+
+ compile
+ compile-custom
+
+
+
+
+
+
+
+
diff --git a/sa-token-demo/sa-token-demo-grpc/server/pom.xml b/sa-token-demo/sa-token-demo-grpc/server/pom.xml
new file mode 100644
index 00000000..a48404a4
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/server/pom.xml
@@ -0,0 +1,20 @@
+
+
+
+ sa-token-demo-grpc
+ com.lym
+ 0.0.1-SNAPSHOT
+
+ 4.0.0
+
+ server
+
+
+ 8
+ 8
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/Server.java b/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/Server.java
new file mode 100644
index 00000000..f9314ac7
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/Server.java
@@ -0,0 +1,18 @@
+package com.lym;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 10:58
+ **/
+@SpringBootApplication
+@EnableDiscoveryClient
+public class Server {
+ public static void main(String[] args) {
+ SpringApplication.run(Server.class);
+ }
+}
diff --git a/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/grpc/server/GrpcAuthService.java b/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/grpc/server/GrpcAuthService.java
new file mode 100644
index 00000000..40cf0c83
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/grpc/server/GrpcAuthService.java
@@ -0,0 +1,37 @@
+package com.lym.grpc.server;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.google.protobuf.Empty;
+import com.lym.grpc.auth.Auth;
+import com.lym.grpc.auth.AuthServiceGrpc;
+import com.lym.service.AuthService;
+import io.grpc.stub.StreamObserver;
+import net.devh.boot.grpc.server.service.GrpcService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 11:29
+ **/
+@GrpcService
+public class GrpcAuthService extends AuthServiceGrpc.AuthServiceImplBase {
+
+ @Autowired
+ private AuthService authService;
+
+ @Override
+ public void isLogin(Empty request, StreamObserver responseObserver) {
+ boolean isLogin = authService.isLogin();
+ responseObserver.onNext(Auth.GrpcBool.newBuilder().setVal(isLogin).build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void login(Auth.GrpcInt request, StreamObserver responseObserver) {
+ StpUtil.login(request.getVal());
+ Auth.GrpcString resp = Auth.GrpcString.newBuilder().setVal(StpUtil.getTokenValue()).build();
+ responseObserver.onNext(resp);
+ responseObserver.onCompleted();
+ }
+}
diff --git a/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/service/AuthService.java b/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/service/AuthService.java
new file mode 100644
index 00000000..f14ce36b
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/server/src/main/java/com/lym/service/AuthService.java
@@ -0,0 +1,23 @@
+package com.lym.service;
+
+import cn.dev33.satoken.stp.StpUtil;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 11:30
+ **/
+@Service
+public class AuthService {
+ public boolean isLogin() {
+ if (StpUtil.isLogin()) {
+ System.out.println("id:" + StpUtil.getLoginIdAsInt());
+ System.out.println("token:" + StpUtil.getTokenValue());
+ } else {
+ System.out.println("未登录");
+ }
+
+ return StpUtil.isLogin();
+ }
+}
diff --git a/sa-token-demo/sa-token-demo-grpc/server/src/main/proto/auth.proto b/sa-token-demo/sa-token-demo-grpc/server/src/main/proto/auth.proto
new file mode 100644
index 00000000..2113a5d4
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/server/src/main/proto/auth.proto
@@ -0,0 +1,24 @@
+syntax = "proto3";
+
+package auth;
+
+option java_package = "com.lym.grpc.auth";
+import "google/protobuf/empty.proto";
+
+message GrpcBool{
+ bool val = 1;
+}
+
+message GrpcInt{
+ int32 val = 1;
+}
+
+message GrpcString{
+ string val = 1;
+}
+
+
+service AuthService{
+ rpc isLogin(google.protobuf.Empty) returns (GrpcBool);
+ rpc login(GrpcInt) returns (GrpcString);
+}
\ No newline at end of file
diff --git a/sa-token-demo/sa-token-demo-grpc/server/src/main/resources/application.yml b/sa-token-demo/sa-token-demo-grpc/server/src/main/resources/application.yml
new file mode 100644
index 00000000..feff9074
--- /dev/null
+++ b/sa-token-demo/sa-token-demo-grpc/server/src/main/resources/application.yml
@@ -0,0 +1,16 @@
+server:
+ port: 5555
+spring:
+ application:
+ name: test-server
+ redis:
+ host: localhost
+ cloud:
+ nacos:
+ server-addr: localhost:8848
+sa-token:
+ is-read-cookie: false
+
+grpc:
+ server:
+ port: 5556
diff --git a/sa-token-doc/doc/plugin/grpc-extend.md b/sa-token-doc/doc/plugin/grpc-extend.md
new file mode 100644
index 00000000..8e3d0e96
--- /dev/null
+++ b/sa-token-doc/doc/plugin/grpc-extend.md
@@ -0,0 +1,39 @@
+# 和 grpc 集成
+
+本插件的作用是让 Sa-Token 和 grpc 做一个整合。
+
+---
+
+和dubbo插件一样,解决了以下问题
+
+1. 在 [ 被调用端 ] 安全的调用 Sa-Token 相关 API。
+2. 在 [ 调用端 ] 登录的会话,其登录状态可以自动传递到 [ 被调用端 ] ;在 [ 被调用端 ] 登录的会话,其登录状态可以自动回传到 [ 调用端 ]
+3. id-token 安全校验
+
+---
+和dubbo插件一样,具有以下限制:
+
+1. [ 调用端 ] 与 [ 被调用端 ] 的 `SaStorage` 数据无法互通。
+2. [ 被调用端 ] 执行的 `SaResponse.setHeader()`、`setStatus()` 等代码无效。
+
+### 引入插件
+需要springboot环境,添加依赖(调用端和被调用端都需要引入):
+
+``` xml
+
+
+ cn.dev33
+ sa-token-context-grpc
+ ${sa.top.version}
+
+```
+
+---
+### 开启id-token校验:
+直接在 `application.yml` 配置即可:
+
+``` yml
+sa-token:
+ # 打开 RPC 调用鉴权
+ check-id-token: true
+```
\ No newline at end of file
diff --git a/sa-token-plugin/pom.xml b/sa-token-plugin/pom.xml
index 36c831c7..127b8180 100644
--- a/sa-token-plugin/pom.xml
+++ b/sa-token-plugin/pom.xml
@@ -31,6 +31,7 @@
sa-token-temp-jwt
sa-token-jwt
sa-token-context-dubbo
+ sa-token-context-grpc
diff --git a/sa-token-plugin/sa-token-context-grpc/pom.xml b/sa-token-plugin/sa-token-context-grpc/pom.xml
new file mode 100644
index 00000000..348e9ed8
--- /dev/null
+++ b/sa-token-plugin/sa-token-context-grpc/pom.xml
@@ -0,0 +1,35 @@
+
+
+
+ sa-token-plugin
+ cn.dev33
+ ${revision}
+ ../pom.xml
+
+ 4.0.0
+
+ jar
+
+ sa-token-context-grpc
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+ net.devh
+ grpc-spring-boot-starter
+ 2.10.1.RELEASE
+
+
+ cn.dev33
+ sa-token-core
+ ${revision}
+
+
+
\ No newline at end of file
diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextCreatorForGrpc.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextCreatorForGrpc.java
new file mode 100644
index 00000000..52a6fb8c
--- /dev/null
+++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextCreatorForGrpc.java
@@ -0,0 +1,20 @@
+package cn.dev33.satoken.context.grpc;
+
+import cn.dev33.satoken.context.second.SaTokenSecondContext;
+import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
+import org.springframework.stereotype.Component;
+
+/**
+ * Sa-Token 二级Context - 创建器 [Grpc版]
+ *
+ * @author lym
+ */
+@Component
+public class SaTokenSecondContextCreatorForGrpc implements SaTokenSecondContextCreator {
+
+ @Override
+ public SaTokenSecondContext create() {
+ return new SaTokenSecondContextForGrpc();
+ }
+
+}
diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextForGrpc.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextForGrpc.java
new file mode 100644
index 00000000..6b156879
--- /dev/null
+++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/SaTokenSecondContextForGrpc.java
@@ -0,0 +1,45 @@
+package cn.dev33.satoken.context.grpc;
+
+import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext;
+import cn.dev33.satoken.context.grpc.model.SaRequestForGrpc;
+import cn.dev33.satoken.context.grpc.model.SaResponseForGrpc;
+import cn.dev33.satoken.context.grpc.model.SaStorageForGrpc;
+import cn.dev33.satoken.context.model.SaRequest;
+import cn.dev33.satoken.context.model.SaResponse;
+import cn.dev33.satoken.context.model.SaStorage;
+import cn.dev33.satoken.context.second.SaTokenSecondContext;
+import cn.dev33.satoken.exception.ApiDisabledException;
+
+/**
+ * Sa-Token 上下文 [grpc版本]
+ *
+ * @author lym
+ */
+public class SaTokenSecondContextForGrpc implements SaTokenSecondContext {
+
+ @Override
+ public SaRequest getRequest() {
+ return new SaRequestForGrpc();
+ }
+
+ @Override
+ public SaResponse getResponse() {
+ return new SaResponseForGrpc();
+ }
+
+ @Override
+ public SaStorage getStorage() {
+ return new SaStorageForGrpc();
+ }
+
+ @Override
+ public boolean matchPath(String pattern, String path) {
+ throw new ApiDisabledException();
+ }
+
+ @Override
+ public boolean isValid() {
+ return SaTokenGrpcContext.isNotNull();
+ }
+
+}
diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/constants/GrpcContextConstants.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/constants/GrpcContextConstants.java
new file mode 100644
index 00000000..2193c62d
--- /dev/null
+++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/constants/GrpcContextConstants.java
@@ -0,0 +1,19 @@
+package cn.dev33.satoken.context.grpc.constants;
+
+import cn.dev33.satoken.id.SaIdUtil;
+import cn.dev33.satoken.util.SaTokenConsts;
+import io.grpc.Metadata;
+
+/**
+ * @author lym
+ * @description
+ * @date 2022/8/26 14:27
+ **/
+public class GrpcContextConstants {
+ public static final Metadata.Key SA_ID_TOKEN =
+ Metadata.Key.of(SaIdUtil.ID_TOKEN, Metadata.ASCII_STRING_MARSHALLER);
+
+ public static final Metadata.Key SA_JUST_CREATED_NOT_PREFIX =
+ Metadata.Key.of(SaTokenConsts.JUST_CREATED_NOT_PREFIX, Metadata.ASCII_STRING_MARSHALLER);
+
+}
diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/context/SaTokenGrpcContext.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/context/SaTokenGrpcContext.java
new file mode 100644
index 00000000..353061f4
--- /dev/null
+++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/context/SaTokenGrpcContext.java
@@ -0,0 +1,44 @@
+package cn.dev33.satoken.context.grpc.context;
+
+import io.grpc.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author lym
+ * @date 2022/8/25 11:02
+ **/
+public class SaTokenGrpcContext {
+ /**
+ * grpc请求上下文。请求完成后会由grpc自动清空
+ *
+ * @see Contexts#interceptCall(Context, ServerCall, Metadata, ServerCallHandler)
+ */
+ private static final Context.Key