From fb4b4cba876d1ac02d8ed5b8208ef271569db4c0 Mon Sep 17 00:00:00 2001
From: landaiqing <3517283258@qq.com>
Date: Tue, 7 May 2024 19:53:11 +0800
Subject: [PATCH] feat: update gateway module
---
schisandra-cloud-storage-gateway/pom.xml | 117 +++++++++++++++++-
.../gateway/GatewayApplication.java | 19 +++
.../gateway/auth/SaTokenConfigure.java | 32 +++++
.../gateway/auth/StpInterfaceImpl.java | 62 ++++++++++
.../gateway/entity/AuthPermission.java | 53 ++++++++
.../schisandra/gateway/entity/AuthRole.java | 42 +++++++
.../com/schisandra/gateway/entity/Result.java | 59 +++++++++
.../gateway/enums/ResultCodeEnum.java | 24 ++++
.../exception/GatewayExceptionHandler.java | 55 ++++++++
.../gateway/filter/LoginFilter.java | 46 +++++++
.../schisandra/gateway/redis/RedisConfig.java | 49 ++++++++
.../schisandra/gateway/redis/RedisUtil.java | 107 ++++++++++++++++
.../src/main/resources/application.yml | 57 +++++++++
.../src/main/resources/bootstrap.yml | 17 +++
14 files changed, 738 insertions(+), 1 deletion(-)
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/GatewayApplication.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/SaTokenConfigure.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/StpInterfaceImpl.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthPermission.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthRole.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/Result.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/enums/ResultCodeEnum.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/exception/GatewayExceptionHandler.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/filter/LoginFilter.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/redis/RedisConfig.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/redis/RedisUtil.java
create mode 100644 schisandra-cloud-storage-gateway/src/main/resources/application.yml
create mode 100644 schisandra-cloud-storage-gateway/src/main/resources/bootstrap.yml
diff --git a/schisandra-cloud-storage-gateway/pom.xml b/schisandra-cloud-storage-gateway/pom.xml
index ef44845..64e2261 100644
--- a/schisandra-cloud-storage-gateway/pom.xml
+++ b/schisandra-cloud-storage-gateway/pom.xml
@@ -9,10 +9,125 @@
schisandra-cloud-storage-gateway
+ 8
+ 8
+ 1.8
UTF-8
+ UTF-8
+ 2.4.2
+ 2021.1
+ 2020.0.6
-
+
+
+
+ org.projectlombok
+ lombok
+ 1.18.20
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-config
+
+
+ org.springframework.cloud
+ spring-cloud-starter-bootstrap
+
+
+ com.alibaba.cloud
+ spring-cloud-starter-alibaba-nacos-discovery
+
+
+ org.springframework.cloud
+ spring-cloud-starter-gateway
+
+
+ org.springframework.cloud
+ spring-cloud-loadbalancer
+
+
+
+ cn.dev33
+ sa-token-reactor-spring-boot-starter
+ 1.37.0
+
+
+
+
+ cn.dev33
+ sa-token-redis-jackson
+ 1.37.0
+
+
+ org.apache.commons
+ commons-pool2
+
+
+ com.google.code.gson
+ gson
+ 2.8.9
+
+
+
+
+
+ org.springframework.cloud
+ spring-cloud-dependencies
+ ${spring-cloud.version}
+ pom
+ import
+
+
+ org.springframework.boot
+ spring-boot-dependencies
+ ${spring-boot.version}
+ pom
+ import
+
+
+ com.alibaba.cloud
+ spring-cloud-alibaba-dependencies
+ ${spring-cloud-alibaba.version}
+ pom
+ import
+
+
+
+
+
+ ${project.artifactId}
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ 2.3.0.RELEASE
+
+
+
+ repackage
+
+
+
+
+
+
+
+
+
+ central
+ aliyun maven
+ http://maven.aliyun.com/nexus/content/groups/public/
+ default
+
+ true
+
+
+ true
+
+
+
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/GatewayApplication.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/GatewayApplication.java
new file mode 100644
index 0000000..f4405ab
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/GatewayApplication.java
@@ -0,0 +1,19 @@
+package com.schisandra.gateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.ComponentScan;
+
+/**
+ * 网关启动类
+ *
+ * @author: landaiqing
+ * @date: 2024/2/7
+ */
+@SpringBootApplication
+@ComponentScan("com.schisandra")
+public class GatewayApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(GatewayApplication.class);
+ }
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/SaTokenConfigure.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/SaTokenConfigure.java
new file mode 100644
index 0000000..0ddc1d7
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/SaTokenConfigure.java
@@ -0,0 +1,32 @@
+package com.schisandra.gateway.auth;
+
+import cn.dev33.satoken.context.SaHolder;
+import cn.dev33.satoken.reactor.filter.SaReactorFilter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 权限认证的配置器
+ *
+ * @author: landaiqing
+ */
+@Configuration
+public class SaTokenConfigure {
+
+ @Bean
+ public SaReactorFilter getSaReactorFilter() {
+ return new SaReactorFilter()
+ // 拦截地址
+ .addInclude("/**")
+ // 鉴权方法:每次访问进入
+ .setAuth(obj -> {
+ System.out.println("-------- 前端访问path:" + SaHolder.getRequest().getRequestPath());
+ // 登录校验 -- 拦截所有路由,并排除/user/doLogin 用于开放登录
+ //SaRouter.match("/auth/**", "/auth/user/doLogin", r -> StpUtil.checkRole("admin"));
+// SaRouter.match("/oss/**", r -> StpUtil.checkLogin());
+// SaRouter.match("/subject/subject/add", r -> StpUtil.checkPermission("subject:add"));
+// SaRouter.match("/subject/**", r -> StpUtil.checkLogin());
+ })
+ ;
+ }
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/StpInterfaceImpl.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/StpInterfaceImpl.java
new file mode 100644
index 0000000..0e77b9d
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/auth/StpInterfaceImpl.java
@@ -0,0 +1,62 @@
+package com.schisandra.gateway.auth;
+
+import cn.dev33.satoken.stp.StpInterface;
+import com.alibaba.cloud.commons.lang.StringUtils;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.schisandra.gateway.entity.AuthPermission;
+import com.schisandra.gateway.entity.AuthRole;
+import com.schisandra.gateway.redis.RedisUtil;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 自定义权限验证接口扩展
+ *
+ * @author: landaiqing
+ */
+@Component
+public class StpInterfaceImpl implements StpInterface {
+
+ @Resource
+ private RedisUtil redisUtil;
+
+ private String authPermissionPrefix = "auth.permission";
+
+ private String authRolePrefix = "auth.role";
+
+ @Override
+ public List getPermissionList(Object loginId, String loginType) {
+ return getAuth(loginId.toString(), authPermissionPrefix);
+ }
+
+ @Override
+ public List getRoleList(Object loginId, String loginType) {
+ return getAuth(loginId.toString(), authRolePrefix);
+ }
+
+ private List getAuth(String loginId, String prefix) {
+ String authKey = redisUtil.buildKey(prefix, loginId.toString());
+ String authValue = redisUtil.get(authKey);
+ if (StringUtils.isBlank(authValue)) {
+ return Collections.emptyList();
+ }
+ List authList = new LinkedList<>();
+ if (authRolePrefix.equals(prefix)) {
+ List roleList = new Gson().fromJson(authValue, new TypeToken>() {
+ }.getType());
+ authList = roleList.stream().map(AuthRole::getRoleKey).collect(Collectors.toList());
+ } else if (authPermissionPrefix.equals(prefix)) {
+ List permissionList = new Gson().fromJson(authValue, new TypeToken>() {
+ }.getType());
+ authList = permissionList.stream().map(AuthPermission::getPermissionKey).collect(Collectors.toList());
+ }
+ return authList;
+ }
+
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthPermission.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthPermission.java
new file mode 100644
index 0000000..8d13f83
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthPermission.java
@@ -0,0 +1,53 @@
+package com.schisandra.gateway.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * (AuthPermission)实体类
+ *
+ * @author landaiqing
+ */
+@Data
+public class AuthPermission implements Serializable {
+ private Long id;
+
+ private String name;
+
+ private Long parentId;
+
+ private Integer type;
+
+ private String menuUrl;
+
+ private Integer status;
+
+ private Integer show;
+
+ private String icon;
+
+ private String permissionKey;
+ /**
+ * 创建人
+ */
+ private String createdBy;
+ /**
+ * 创建时间
+ */
+ private Date createdTime;
+ /**
+ * 更新人
+ */
+ private String updateBy;
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+ private Integer isDeleted;
+
+
+}
+
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthRole.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthRole.java
new file mode 100644
index 0000000..b61acd6
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/AuthRole.java
@@ -0,0 +1,42 @@
+package com.schisandra.gateway.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * (AuthRole)实体类
+ *
+ * @author landaiqing
+ * @since 2024-2-18 18:55:50
+ */
+@Data
+public class AuthRole implements Serializable {
+
+ private Long id;
+
+ private String roleName;
+
+ private String roleKey;
+ /**
+ * 创建人
+ */
+ private String createdBy;
+ /**
+ * 创建时间
+ */
+ private Date createdTime;
+ /**
+ * 更新人
+ */
+ private String updateBy;
+ /**
+ * 更新时间
+ */
+ private Date updateTime;
+
+ private Integer isDeleted;
+
+}
+
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/Result.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/Result.java
new file mode 100644
index 0000000..5b8713a
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/entity/Result.java
@@ -0,0 +1,59 @@
+package com.schisandra.gateway.entity;
+
+import com.schisandra.gateway.enums.ResultCodeEnum;
+import lombok.Data;
+
+@Data
+public class Result {
+
+ private Boolean success;
+
+ private Integer code;
+
+ private String message;
+
+ private T data;
+
+ public static Result ok(){
+ Result result = new Result();
+ result.setSuccess(true);
+ result.setCode(ResultCodeEnum.SUCCESS.getCode());
+ result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
+ return result;
+ }
+
+ public static Result ok(T data){
+ Result result = new Result();
+ result.setSuccess(true);
+ result.setCode(ResultCodeEnum.SUCCESS.getCode());
+ result.setMessage(ResultCodeEnum.SUCCESS.getDesc());
+ result.setData(data);
+ return result;
+ }
+
+ public static Result fail(){
+ Result result = new Result();
+ result.setSuccess(false);
+ result.setCode(ResultCodeEnum.FAIL.getCode());
+ result.setMessage(ResultCodeEnum.FAIL.getDesc());
+ return result;
+ }
+
+ public static Result fail(T data){
+ Result result = new Result();
+ result.setSuccess(false);
+ result.setCode(ResultCodeEnum.FAIL.getCode());
+ result.setMessage(ResultCodeEnum.FAIL.getDesc());
+ result.setData(data);
+ return result;
+ }
+
+ public static Result fail(Integer code,String message){
+ Result result = new Result();
+ result.setSuccess(false);
+ result.setCode(code);
+ result.setMessage(message);
+ return result;
+ }
+
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/enums/ResultCodeEnum.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/enums/ResultCodeEnum.java
new file mode 100644
index 0000000..3addbda
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/enums/ResultCodeEnum.java
@@ -0,0 +1,24 @@
+package com.schisandra.gateway.enums;
+
+import lombok.Getter;
+
+@Getter
+public enum ResultCodeEnum {
+ SUCCESS(200,"成功"),
+ FAIL(500,"失败");
+ private int code;
+ private String desc;
+
+ ResultCodeEnum(int code,String desc){
+ this.code=code;
+ this.desc=desc;
+ }
+ public static ResultCodeEnum getByCode(int codeVal){
+ for(ResultCodeEnum resultCodeEnum:ResultCodeEnum.values()){
+ if(resultCodeEnum.code==codeVal){
+ return resultCodeEnum;
+ }
+ }
+ return null;
+ }
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/exception/GatewayExceptionHandler.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/exception/GatewayExceptionHandler.java
new file mode 100644
index 0000000..9444e35
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/exception/GatewayExceptionHandler.java
@@ -0,0 +1,55 @@
+package com.schisandra.gateway.exception;
+
+import cn.dev33.satoken.exception.SaTokenException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.schisandra.gateway.entity.Result;
+import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
+import org.springframework.core.io.buffer.DataBufferFactory;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * @Classname GatewayExceptionHandler
+ * @BelongsProject: qing-yu-club
+ * @BelongsPackage: com.landaiqing.club.gateway.exception
+ * @Author: landaiqing
+ * @CreateTime: 2024-05-18 17:52
+ * @Description: 网关全局异常处理
+ * @Version: 1.0
+ */
+@Component
+public class GatewayExceptionHandler implements ErrorWebExceptionHandler {
+ private ObjectMapper objectMapper=new ObjectMapper();
+ @Override
+ public Mono handle(ServerWebExchange serverWebExchange, Throwable throwable) {
+ ServerHttpRequest request = serverWebExchange.getRequest();
+ ServerHttpResponse response = serverWebExchange.getResponse();
+ Integer code=200;
+ String message="";
+ if(throwable instanceof SaTokenException){
+ code=401;
+ message="用户无权限";
+ }else {
+ code=500;
+ message="系统繁忙";
+ }
+ Result result = Result.fail(code, message);
+ response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
+ return response.writeWith(Mono.fromSupplier(()->{
+ DataBufferFactory dataBufferFactory=response.bufferFactory();
+ byte[] bytes=null;
+ try {
+ bytes = objectMapper.writeValueAsBytes(result);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ return dataBufferFactory.wrap(bytes);
+ }));
+
+ }
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/filter/LoginFilter.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/filter/LoginFilter.java
new file mode 100644
index 0000000..2461c13
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/filter/LoginFilter.java
@@ -0,0 +1,46 @@
+package com.schisandra.gateway.filter;
+
+import cn.dev33.satoken.stp.SaTokenInfo;
+import cn.dev33.satoken.stp.StpUtil;
+import lombok.SneakyThrows;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+/**
+ * @Classname LoginFilter
+ * @BelongsProject: qing-yu-club
+ * @BelongsPackage: com.landaiqing.club.gateway.filter
+ * @Author: landaiqing
+ * @CreateTime: 2024-03-03 17:41
+ * @Description: 登录拦截器
+ * @Version: 1.0
+ */
+@Component
+@Slf4j
+public class LoginFilter implements GlobalFilter {
+ @Override
+ @SneakyThrows
+ public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+ ServerHttpRequest request = exchange.getRequest();
+ ServerHttpRequest.Builder mutate = request.mutate();
+ String url = request.getURI().getPath();
+ log.info("LoginFilter.filter.url:{}", url);
+ if (url.equals("/user/doLogin") || url.equals("/user/getUserInfo")) {
+ return chain.filter(exchange);
+ }
+ SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
+ String loginId = (String) tokenInfo.getLoginId();
+ if (StringUtils.isEmpty(loginId)) {
+ throw new Exception("未获取到用户信息");
+ }
+ mutate.header("loginId", loginId);
+
+ return chain.filter(exchange.mutate().request(mutate.build()).build());
+ }
+}
diff --git a/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/redis/RedisConfig.java b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/redis/RedisConfig.java
new file mode 100644
index 0000000..2e505fb
--- /dev/null
+++ b/schisandra-cloud-storage-gateway/src/main/java/com/schisandra/gateway/redis/RedisConfig.java
@@ -0,0 +1,49 @@
+package com.schisandra.gateway.redis;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * @Classname RedisConfig
+ * @BelongsProject: qing-yu-club
+ * @BelongsPackage: com.landaiqing.club.gateway.redis
+ * @Author: landaiqing
+ * @CreateTime: 2024-02-18 18:10
+ * @Description: redis的config处理
+ * @Version: 1.0
+ */
+@Configuration
+public class RedisConfig {
+ @Bean
+ public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+ RedisTemplate redisTemplate = new RedisTemplate<>();
+ RedisSerializer redisSerializer = new StringRedisSerializer();
+ redisTemplate.setConnectionFactory(redisConnectionFactory);
+ redisTemplate.setKeySerializer(redisSerializer);
+ redisTemplate.setHashKeySerializer(redisSerializer);
+ redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
+ redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());
+ return redisTemplate;
+ }
+
+ private Jackson2JsonRedisSerializer