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> SA_TOKEN_CONTEXT_KEY = + Context.key("sa-token-context"); + + public static Object get(String key) { + return SA_TOKEN_CONTEXT_KEY.get().get(key); + } + + public static void set(String key, Object value) { + SA_TOKEN_CONTEXT_KEY.get().put(key, value); + } + + public static void removeKey(String key) { + SA_TOKEN_CONTEXT_KEY.get().remove(key); + } + + public static Map getContext() { + return SA_TOKEN_CONTEXT_KEY.get(); + } + + public static boolean isNotNull() { + return SA_TOKEN_CONTEXT_KEY.get() != null; + } + + public static Context create() { + return Context.current().withValue(SaTokenGrpcContext.SA_TOKEN_CONTEXT_KEY, new HashMap<>()); + } +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenContextGrpcServerInterceptor.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenContextGrpcServerInterceptor.java new file mode 100644 index 00000000..b5acf793 --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenContextGrpcServerInterceptor.java @@ -0,0 +1,28 @@ +package cn.dev33.satoken.context.grpc.interceptor; + +import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext; +import io.grpc.*; +import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor; +import org.springframework.core.Ordered; + +/** + * @author lym + * @date 2022/8/24 10:09 + * @description 处理请求前,创建上下文 + */ +@GrpcGlobalServerInterceptor +public class SaTokenContextGrpcServerInterceptor implements ServerInterceptor, Ordered { + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler next) { + Context ctx = SaTokenGrpcContext.create(); + return Contexts.interceptCall(ctx, call, headers, next); + } + + /** + * 必须最先创建上下文,后面的拦截器才能获取到上下文 + */ + @Override + public int getOrder() { + return HIGHEST_PRECEDENCE; + } +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcClientInterceptor.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcClientInterceptor.java new file mode 100644 index 00000000..44db31d6 --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcClientInterceptor.java @@ -0,0 +1,59 @@ +package cn.dev33.satoken.context.grpc.interceptor; + +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.context.SaTokenContextDefaultImpl; +import cn.dev33.satoken.context.grpc.constants.GrpcContextConstants; +import cn.dev33.satoken.id.SaIdUtil; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import io.grpc.*; +import net.devh.boot.grpc.client.interceptor.GrpcGlobalClientInterceptor; +import org.springframework.core.Ordered; + + +/** + * @author lym + * @date 2022/8/24 15:45 + * @description 客户端请求的时候,带上token + */ +@GrpcGlobalClientInterceptor +public class SaTokenGrpcClientInterceptor implements ClientInterceptor, Ordered { + @Override + public ClientCall interceptCall(MethodDescriptor method, + CallOptions callOptions, Channel next) { + return new ForwardingClientCall.SimpleForwardingClientCall(next.newCall(method, callOptions)) { + @Override + public void start(Listener responseListener, Metadata headers) { + + // 追加 Id-Token 参数 + if (SaManager.getConfig().getCheckIdToken()) { + headers.put(GrpcContextConstants.SA_ID_TOKEN, SaIdUtil.getToken()); + } + + // 调用前,传递会话Token + String tokenValue = StpUtil.getTokenValue(); + if (SaFoxUtil.isNotEmpty(tokenValue) + && SaManager.getSaTokenContextOrSecond() != SaTokenContextDefaultImpl.defaultContext) { + headers.put(GrpcContextConstants.SA_JUST_CREATED_NOT_PREFIX, tokenValue); + } + + super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener(responseListener) { + /** + * 服务端结束响应后,解析回传的Token值 + */ + @Override + public void onClose(Status status, Metadata responseHeader) { + StpUtil.setTokenValue(responseHeader.get(GrpcContextConstants.SA_JUST_CREATED_NOT_PREFIX)); + super.onClose(status, responseHeader); + } + }, headers); + } + }; + } + + + @Override + public int getOrder() { + return HIGHEST_PRECEDENCE; + } +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcServerInterceptor.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcServerInterceptor.java new file mode 100644 index 00000000..6bfd9511 --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/interceptor/SaTokenGrpcServerInterceptor.java @@ -0,0 +1,42 @@ +package cn.dev33.satoken.context.grpc.interceptor; + +import cn.dev33.satoken.SaManager; +import cn.dev33.satoken.context.grpc.constants.GrpcContextConstants; +import cn.dev33.satoken.id.SaIdUtil; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.util.SaFoxUtil; +import io.grpc.*; +import net.devh.boot.grpc.server.interceptor.GrpcGlobalServerInterceptor; + +/** + * @author lym + * @description 鉴权,设置token + * @date 2022/8/25 11:33 + **/ +@GrpcGlobalServerInterceptor +public class SaTokenGrpcServerInterceptor implements ServerInterceptor { + @Override + public ServerCall.Listener interceptCall(ServerCall call, Metadata headers, ServerCallHandler next) { + // RPC 调用鉴权 + if (SaManager.getConfig().getCheckIdToken()) { + String idToken = headers.get(GrpcContextConstants.SA_ID_TOKEN); + SaIdUtil.checkToken(idToken); + } + String tokenFromClient = headers.get(GrpcContextConstants.SA_JUST_CREATED_NOT_PREFIX); + StpUtil.setTokenValue(tokenFromClient); + + return next.startCall(new ForwardingServerCall.SimpleForwardingServerCall(call) { + /** + * 结束响应时,若本服务生成了新token,将其传回客户端 + */ + @Override + public void close(Status status, Metadata responseHeaders) { + String justCreateToken = StpUtil.getTokenValue(); + if (!SaFoxUtil.equals(justCreateToken, tokenFromClient) && SaFoxUtil.isNotEmpty(justCreateToken)) { + responseHeaders.put(GrpcContextConstants.SA_JUST_CREATED_NOT_PREFIX, justCreateToken); + } + super.close(status, responseHeaders); + } + }, headers); + } +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java new file mode 100644 index 00000000..269878bd --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaRequestForGrpc.java @@ -0,0 +1,85 @@ +package cn.dev33.satoken.context.grpc.model; + +import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext; +import cn.dev33.satoken.context.model.SaRequest; + +/** + * Request for grpc + * + * @author lym + */ +public class SaRequestForGrpc implements SaRequest { + + /** + * 获取底层源对象 + */ + @Override + public Object getSource() { + return SaTokenGrpcContext.getContext(); + } + + /** + * 在 [请求体] 里获取一个值 + */ + @Override + public String getParam(String name) { + // 不传播 url 参数 + return null; + } + + /** + * 在 [请求头] 里获取一个值 + */ + @Override + public String getHeader(String name) { + // 不传播 header 参数 + return null; + } + + /** + * 在 [Cookie作用域] 里获取一个值 + */ + @Override + public String getCookieValue(String name) { + // 不传播 cookie 参数 + return null; + } + + /** + * 返回当前请求path (不包括上下文名称) + */ + @Override + public String getRequestPath() { + // 不传播 requestPath + return null; + } + + /** + * 返回当前请求的url,例:http://xxx.com/test + * + * @return see note + */ + public String getUrl() { + // 不传播 url + return null; + } + + /** + * 返回当前请求的类型 + */ + @Override + public String getMethod() { + // 不传播 method + return null; + } + + /** + * 转发请求 + */ + @Override + public Object forward(String path) { + // 不传播 forward 动作 + return null; + } + +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaResponseForGrpc.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaResponseForGrpc.java new file mode 100644 index 00000000..664b73b9 --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaResponseForGrpc.java @@ -0,0 +1,60 @@ +package cn.dev33.satoken.context.grpc.model; + +import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext; +import cn.dev33.satoken.context.model.SaResponse; + +/** + * Response for grpc + * + * @author lym + */ +public class SaResponseForGrpc implements SaResponse { + /** + * 获取底层源对象 + */ + @Override + public Object getSource() { + return SaTokenGrpcContext.getContext(); + } + + /** + * 设置响应状态码 + */ + @Override + public SaResponse setStatus(int sc) { + // 不回传 status 状态 + return this; + } + + /** + * 在响应头里写入一个值 + */ + @Override + public SaResponse setHeader(String name, String value) { + // 不回传 header响应头 + return this; + } + + /** + * 在响应头里添加一个值 + * + * @param name 名字 + * @param value 值 + * @return 对象自身 + */ + public SaResponse addHeader(String name, String value) { + // 不回传 header响应头 + return this; + } + + /** + * 重定向 + */ + @Override + public Object redirect(String url) { + // 不回传 重定向 动作 + return null; + } + + +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaStorageForGrpc.java b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaStorageForGrpc.java new file mode 100644 index 00000000..e797636c --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/java/cn/dev33/satoken/context/grpc/model/SaStorageForGrpc.java @@ -0,0 +1,47 @@ +package cn.dev33.satoken.context.grpc.model; + +import cn.dev33.satoken.context.grpc.context.SaTokenGrpcContext; +import cn.dev33.satoken.context.model.SaStorage; + +/** + * Storage for grpc + * + * @author lym + */ +public class SaStorageForGrpc implements SaStorage { + + /** + * 获取底层源对象 + */ + @Override + public Object getSource() { + return SaTokenGrpcContext.getContext(); + } + + /** + * 在 [Request作用域] 里写入一个值 + */ + @Override + public SaStorage set(String key, Object value) { + SaTokenGrpcContext.set(key, value); + return this; + } + + /** + * 在 [Request作用域] 里获取一个值 + */ + @Override + public Object get(String key) { + return SaTokenGrpcContext.get(key); + } + + /** + * 在 [Request作用域] 里删除一个值 + */ + @Override + public SaStorage delete(String key) { + SaTokenGrpcContext.removeKey(key); + return this; + } + +} diff --git a/sa-token-plugin/sa-token-context-grpc/src/main/resources/META-INF/spring.factories b/sa-token-plugin/sa-token-context-grpc/src/main/resources/META-INF/spring.factories new file mode 100644 index 00000000..59ef7b39 --- /dev/null +++ b/sa-token-plugin/sa-token-context-grpc/src/main/resources/META-INF/spring.factories @@ -0,0 +1,5 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ + cn.dev33.satoken.context.grpc.interceptor.SaTokenGrpcClientInterceptor,\ + cn.dev33.satoken.context.grpc.interceptor.SaTokenContextGrpcServerInterceptor,\ + cn.dev33.satoken.context.grpc.interceptor.SaTokenGrpcServerInterceptor,\ + cn.dev33.satoken.context.grpc.SaTokenSecondContextCreatorForGrpc \ No newline at end of file