From 07233324cc95f75e91ab901275aba45bcceff2db Mon Sep 17 00:00:00 2001
From: haoxr <1490493387@qq.com>
Date: Sat, 30 Jan 2021 00:40:26 +0800
Subject: [PATCH] =?UTF-8?q?feat:=E6=BC=94=E7=A4=BA=E7=8E=AF=E5=A2=83?=
=?UTF-8?q?=E7=A6=81=E6=AD=A2=E5=88=A0=E9=99=A4=E5=92=8C=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
youlai-auth/pom.xml | 11 +----
.../common/core/constant/AuthConstants.java | 2 +
.../youlai/common/core/result/ResultCode.java | 6 ++-
youlai-gateway/pom.xml | 1 -
.../gateway/config/ResourceServerConfig.java | 23 ++--------
.../gateway/filter/AuthGlobalFilter.java | 44 ++++++++++++-------
.../com/youlai/gateway/util/WebUtils.java | 25 +++++++++++
7 files changed, 65 insertions(+), 47 deletions(-)
diff --git a/youlai-auth/pom.xml b/youlai-auth/pom.xml
index a8128f267..4923411a3 100644
--- a/youlai-auth/pom.xml
+++ b/youlai-auth/pom.xml
@@ -68,7 +68,6 @@
${youlai.version}
-
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
@@ -98,12 +97,6 @@
spring-boot-configuration-processor
-
- org.springframework.boot
- spring-boot-starter-actuator
-
-
-
org.springframework.cloud
@@ -154,13 +147,13 @@
1.0.0
-
+
diff --git a/youlai-common/common-core/src/main/java/com/youlai/common/core/constant/AuthConstants.java b/youlai-common/common-core/src/main/java/com/youlai/common/core/constant/AuthConstants.java
index c3e9ab03a..c24006fd0 100644
--- a/youlai-common/common-core/src/main/java/com/youlai/common/core/constant/AuthConstants.java
+++ b/youlai-common/common-core/src/main/java/com/youlai/common/core/constant/AuthConstants.java
@@ -49,6 +49,8 @@ public interface AuthConstants {
String JWT_CLIENT_ID_KEY = "client_id";
+ String JWT_JTI_KEY = "client_id";
+
/**
* JWT存储权限前缀
*/
diff --git a/youlai-common/common-core/src/main/java/com/youlai/common/core/result/ResultCode.java b/youlai-common/common-core/src/main/java/com/youlai/common/core/result/ResultCode.java
index bda12bcf2..ebd0fc9d8 100644
--- a/youlai-common/common-core/src/main/java/com/youlai/common/core/result/ResultCode.java
+++ b/youlai-common/common-core/src/main/java/com/youlai/common/core/result/ResultCode.java
@@ -27,8 +27,10 @@ public enum ResultCode implements IResultCode, Serializable {
CLIENT_AUTHENTICATION_FAILED("A0212","客户端认证失败"), // *
TOKEN_INVALID_OR_EXPIRED("A0230","token无效或已过期"),
- USER_AUTHORIZED_ERROR ("A0300","访问权限异常"),
- USER_ACCESS_UNAUTHORIZED ("A0301","访问未授权"),
+ AUTHORIZED_ERROR ("A0300","访问权限异常"),
+ ACCESS_UNAUTHORIZED ("A0301","访问未授权"),
+ FORBIDDEN_OPERATION ("A0302","演示环境禁止修改、删除重要数据,请本地部署后测试"),
+
USER_REQUEST_PARAM_ERROR("A0400","用户请求参数错误"),
USER_REQUEST_PARAM_IS_BLANK("A0410","请求必填参数为空"),
diff --git a/youlai-gateway/pom.xml b/youlai-gateway/pom.xml
index 9b06db924..9cfc4e8b9 100644
--- a/youlai-gateway/pom.xml
+++ b/youlai-gateway/pom.xml
@@ -68,7 +68,6 @@
${youlai.version}
-
org.springframework.cloud
spring-cloud-starter-loadbalancer
diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/config/ResourceServerConfig.java b/youlai-gateway/src/main/java/com/youlai/gateway/config/ResourceServerConfig.java
index d6bca0d4c..5783543de 100644
--- a/youlai-gateway/src/main/java/com/youlai/gateway/config/ResourceServerConfig.java
+++ b/youlai-gateway/src/main/java/com/youlai/gateway/config/ResourceServerConfig.java
@@ -6,6 +6,7 @@ import com.youlai.common.core.constant.AuthConstants;
import com.youlai.common.core.result.Result;
import com.youlai.common.core.result.ResultCode;
import com.youlai.gateway.security.AuthorizationManager;
+import com.youlai.gateway.util.WebUtils;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -66,16 +67,7 @@ public class ResourceServerConfig {
ServerAccessDeniedHandler accessDeniedHandler() {
return (exchange, denied) -> {
Mono mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
- .flatMap(response -> {
- response.setStatusCode(HttpStatus.OK);
- response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
- response.getHeaders().set("Access-Control-Allow-Origin", "*");
- response.getHeaders().set("Cache-Control", "no-cache");
- String body = JSONUtil.toJsonStr(Result.failed(ResultCode.USER_ACCESS_UNAUTHORIZED));
- DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
- return response.writeWith(Mono.just(buffer))
- .doOnError(error -> DataBufferUtils.release(buffer));
- });
+ .flatMap(response ->WebUtils.writeFailedToResponse(response,ResultCode.ACCESS_UNAUTHORIZED));
return mono;
};
@@ -88,16 +80,7 @@ public class ResourceServerConfig {
ServerAuthenticationEntryPoint authenticationEntryPoint() {
return (exchange, e) -> {
Mono mono = Mono.defer(() -> Mono.just(exchange.getResponse()))
- .flatMap(response -> {
- response.setStatusCode(HttpStatus.OK);
- response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
- response.getHeaders().set("Access-Control-Allow-Origin", "*");
- response.getHeaders().set("Cache-Control", "no-cache");
- String body = JSONUtil.toJsonStr(Result.failed(ResultCode.TOKEN_INVALID_OR_EXPIRED));
- DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
- return response.writeWith(Mono.just(buffer))
- .doOnError(error -> DataBufferUtils.release(buffer));
- });
+ .flatMap(response -> WebUtils.writeFailedToResponse(response,ResultCode.TOKEN_INVALID_OR_EXPIRED));
return mono;
};
}
diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/filter/AuthGlobalFilter.java b/youlai-gateway/src/main/java/com/youlai/gateway/filter/AuthGlobalFilter.java
index a3e511e43..242e4645f 100644
--- a/youlai-gateway/src/main/java/com/youlai/gateway/filter/AuthGlobalFilter.java
+++ b/youlai-gateway/src/main/java/com/youlai/gateway/filter/AuthGlobalFilter.java
@@ -7,16 +7,20 @@ import com.nimbusds.jose.JWSObject;
import com.youlai.common.core.constant.AuthConstants;
import com.youlai.common.core.result.Result;
import com.youlai.common.core.result.ResultCode;
+import com.youlai.gateway.util.WebUtils;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
@@ -28,43 +32,53 @@ import reactor.core.publisher.Mono;
import java.nio.charset.Charset;
/**
- * 黑名单token过滤器
+ * 全局过滤器
*/
@Component
@Slf4j
-@AllArgsConstructor
public class AuthGlobalFilter implements GlobalFilter, Ordered {
+ @Autowired
private RedisTemplate redisTemplate;
+ // 是否演示环境
+ @Value("${demo}")
+ private Boolean isDemoEnvironment;
+
@SneakyThrows
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+
+ ServerHttpRequest request = exchange.getRequest();
+ ServerHttpResponse response = exchange.getResponse();
+
+ // 演示环境禁止删除和修改
+ if (isDemoEnvironment && (HttpMethod.PUT.toString().equals(request.getMethodValue()) ||
+ HttpMethod.DELETE.toString().equals(request.getMethodValue())
+ )) {
+ log.warn(ResultCode.FORBIDDEN_OPERATION.getMsg());
+ return WebUtils.writeFailedToResponse(response, ResultCode.FORBIDDEN_OPERATION);
+ }
+
+ // 无token放行
String token = exchange.getRequest().getHeaders().getFirst(AuthConstants.JWT_TOKEN_HEADER);
if (StrUtil.isBlank(token)) {
return chain.filter(exchange);
}
+
+ // 解析JWT获取jti,以jti为key判断redis的黑名单列表是否存在,存在拦截响应token失效
token = token.replace(AuthConstants.JWT_TOKEN_PREFIX, Strings.EMPTY);
JWSObject jwsObject = JWSObject.parse(token);
String payload = jwsObject.getPayload().toString();
-
- // 黑名单token(登出、修改密码)校验
JSONObject jsonObject = JSONUtil.parseObj(payload);
- String jti = jsonObject.getStr("jti"); // JWT唯一标识
-
+ String jti = jsonObject.getStr(AuthConstants.JWT_JTI_KEY);
Boolean isBlack = redisTemplate.hasKey(AuthConstants.TOKEN_BLACKLIST_PREFIX + jti);
if (isBlack) {
- ServerHttpResponse response = exchange.getResponse();
- response.setStatusCode(HttpStatus.OK);
- response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
- response.getHeaders().set("Access-Control-Allow-Origin", "*");
- response.getHeaders().set("Cache-Control", "no-cache");
- String body = JSONUtil.toJsonStr(Result.failed(ResultCode.TOKEN_INVALID_OR_EXPIRED));
- DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
- return response.writeWith(Mono.just(buffer));
+ return WebUtils.writeFailedToResponse(response, ResultCode.TOKEN_INVALID_OR_EXPIRED);
}
- ServerHttpRequest request = exchange.getRequest().mutate()
+ // 存在token且不是黑名单,request写入JWT的载体信息
+ request = exchange.getRequest().mutate()
.header(AuthConstants.JWT_PAYLOAD_KEY, payload)
.build();
exchange = exchange.mutate().request(request).build();
diff --git a/youlai-gateway/src/main/java/com/youlai/gateway/util/WebUtils.java b/youlai-gateway/src/main/java/com/youlai/gateway/util/WebUtils.java
index 6d3a7eec5..2d6cbcb02 100644
--- a/youlai-gateway/src/main/java/com/youlai/gateway/util/WebUtils.java
+++ b/youlai-gateway/src/main/java/com/youlai/gateway/util/WebUtils.java
@@ -1,9 +1,34 @@
package com.youlai.gateway.util;
+import cn.hutool.json.JSONUtil;
+import com.youlai.common.core.result.Result;
+import com.youlai.common.core.result.ResultCode;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.core.io.buffer.DataBufferUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import reactor.core.publisher.Mono;
+
+import java.nio.charset.Charset;
+
/**
* @Author haoxr
* @Date 2021-01-29 13:30
* @Version 1.0.0
*/
public class WebUtils {
+
+ public static Mono writeFailedToResponse(ServerHttpResponse response,ResultCode resultCode){
+ response.setStatusCode(HttpStatus.OK);
+ response.getHeaders().set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
+ response.getHeaders().set("Access-Control-Allow-Origin", "*");
+ response.getHeaders().set("Cache-Control", "no-cache");
+ String body = JSONUtil.toJsonStr(Result.failed(resultCode));
+ DataBuffer buffer = response.bufferFactory().wrap(body.getBytes(Charset.forName("UTF-8")));
+ return response.writeWith(Mono.just(buffer))
+ .doOnError(error -> DataBufferUtils.release(buffer));
+ }
+
}