From 7a35c474d6153189957422264b57df7ce1daed77 Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: Thu, 29 Jul 2021 14:51:27 +0800
Subject: [PATCH] 统一网关错误码响应
---
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java | 10 -
ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java | 10 -
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java | 10 -
ruoyi-ui/src/utils/ruoyi.js | 18 +-
ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java | 10 ++
ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java | 14 --
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java | 2
ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/service/RedisService.java | 11 ++
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java | 10 +
ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java | 66 +++++++++++++
ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java | 83 ++++++++--------
11 files changed, 155 insertions(+), 89 deletions(-)
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
index 8f666dd..c5ccb44 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/constant/CacheConstants.java
@@ -10,7 +10,7 @@
/**
* 令牌自定义标识
*/
- public static final String HEADER = "Authorization";
+ public static final String TOKEN_AUTHENTICATION = "Authorization";
/**
* 令牌前缀
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java
index f2225be..b7b7b66 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/SecurityUtils.java
@@ -42,7 +42,15 @@
*/
public static String getToken(HttpServletRequest request)
{
- String token = ServletUtils.getRequest().getHeader(CacheConstants.HEADER);
+ String token = request.getHeader(CacheConstants.TOKEN_AUTHENTICATION);
+ return replaceTokenPrefix(token);
+ }
+
+ /**
+ * 替换token前缀
+ */
+ public static String replaceTokenPrefix(String token)
+ {
if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
{
token = token.replace(CacheConstants.TOKEN_PREFIX, "");
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java
index 6809f29..51a6141 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/ServletUtils.java
@@ -10,11 +10,19 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
+import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.Constants;
+import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.text.Convert;
+import reactor.core.publisher.Mono;
/**
* 客户端工具类
@@ -213,4 +221,62 @@
return "";
}
}
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param value 响应内容
+ * @return Mono<Void>
+ */
+ public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value)
+ {
+ return webFluxResponseWriter(response, HttpStatus.OK, value, R.FAIL);
+ }
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return Mono<Void>
+ */
+ public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value, int code)
+ {
+ return webFluxResponseWriter(response, HttpStatus.OK, value, code);
+ }
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param status http状态码
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return Mono<Void>
+ */
+ public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code)
+ {
+ return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
+ }
+
+ /**
+ * 设置webflux模型响应
+ *
+ * @param response ServerHttpResponse
+ * @param contentType content-type
+ * @param status http状态码
+ * @param code 响应状态码
+ * @param value 响应内容
+ * @return Mono<Void>
+ */
+ public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code)
+ {
+ response.setStatusCode(status);
+ response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
+ R<?> result = R.fail(code, value.toString());
+ DataBuffer dataBuffer = response.bufferFactory().wrap(JSONObject.toJSONString(result).getBytes());
+ return response.writeWith(Mono.just(dataBuffer));
+ }
}
diff --git a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/service/RedisService.java b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/service/RedisService.java
index 4bf7f70..dd76297 100644
--- a/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/service/RedisService.java
+++ b/ruoyi-common/ruoyi-common-redis/src/main/java/com/ruoyi/common/redis/service/RedisService.java
@@ -75,6 +75,17 @@
}
/**
+ * 判断 key是否存在
+ *
+ * @param key 键
+ * @return true 存在 false不存在
+ */
+ public Boolean hasKey(String key)
+ {
+ return redisTemplate.hasKey(key);
+ }
+
+ /**
* 获得缓存的基本对象。
*
* @param key 缓存键值
diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
index a4e8428..95dd8a4 100644
--- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
@@ -73,6 +73,16 @@
{
// 获取请求携带的令牌
String token = SecurityUtils.getToken(request);
+ return getLoginUser(token);
+ }
+
+ /**
+ * 获取用户身份信息
+ *
+ * @return 用户信息
+ */
+ public LoginUser getLoginUser(String token)
+ {
if (StringUtils.isNotEmpty(token))
{
String userKey = getTokenKey(token);
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
index 3771b46..8517c79 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/AuthFilter.java
@@ -7,19 +7,15 @@
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.DataBufferFactory;
import org.springframework.data.redis.core.ValueOperations;
-import org.springframework.http.HttpStatus;
-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 com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.Constants;
-import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.constant.HttpStatus;
+import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.redis.service.RedisService;
@@ -35,7 +31,7 @@
public class AuthFilter implements GlobalFilter, Ordered
{
private static final Logger log = LoggerFactory.getLogger(AuthFilter.class);
-
+
private final static long EXPIRE_TIME = Constants.TOKEN_EXPIRE * 60;
// 排除过滤的 uri 地址,nacos自行添加
@@ -44,61 +40,68 @@
@Resource(name = "stringRedisTemplate")
private ValueOperations<String, String> sops;
-
+
@Autowired
private RedisService redisService;
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
- String url = exchange.getRequest().getURI().getPath();
+ ServerHttpRequest request = exchange.getRequest();
+ ServerHttpRequest.Builder mutate = request.mutate();
+
+ String url = request.getURI().getPath();
// 跳过不需要验证的路径
if (StringUtils.matches(url, ignoreWhite.getWhites()))
{
return chain.filter(exchange);
}
- String token = getToken(exchange.getRequest());
- if (StringUtils.isBlank(token))
+ String token = getToken(request);
+ if (StringUtils.isEmpty(token))
{
- return setUnauthorizedResponse(exchange, "令牌不能为空");
+ return unauthorizedResponse(exchange, "令牌不能为空");
}
String userStr = sops.get(getTokenKey(token));
- if (StringUtils.isNull(userStr))
+ if (StringUtils.isEmpty(userStr))
{
- return setUnauthorizedResponse(exchange, "登录状态已过期");
+ return unauthorizedResponse(exchange, "登录状态已过期");
}
- JSONObject obj = JSONObject.parseObject(userStr);
- String userid = obj.getString("userid");
- String username = obj.getString("username");
- if (StringUtils.isBlank(userid) || StringUtils.isBlank(username))
+ JSONObject cacheObj = JSONObject.parseObject(userStr);
+ String userid = cacheObj.getString("userid");
+ String username = cacheObj.getString("username");
+ if (StringUtils.isEmpty(userid) || StringUtils.isEmpty(username))
{
- return setUnauthorizedResponse(exchange, "令牌验证失败");
+ return unauthorizedResponse(exchange, "令牌验证失败");
}
-
+
// 设置过期时间
redisService.expire(getTokenKey(token), EXPIRE_TIME);
// 设置用户信息到请求
- ServerHttpRequest mutableReq = exchange.getRequest().mutate().header(CacheConstants.DETAILS_USER_ID, userid)
- .header(CacheConstants.DETAILS_USERNAME, ServletUtils.urlEncode(username)).build();
- ServerWebExchange mutableExchange = exchange.mutate().request(mutableReq).build();
-
- return chain.filter(mutableExchange);
+ addHeader(mutate, CacheConstants.DETAILS_USER_ID, userid);
+ addHeader(mutate, CacheConstants.DETAILS_USERNAME, username);
+ return chain.filter(exchange.mutate().request(mutate.build()).build());
}
- private Mono<Void> setUnauthorizedResponse(ServerWebExchange exchange, String msg)
+ private void addHeader(ServerHttpRequest.Builder mutate, String name, Object value)
{
- ServerHttpResponse response = exchange.getResponse();
- response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
- response.setStatusCode(HttpStatus.OK);
-
- log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
-
- return response.writeWith(Mono.fromSupplier(() -> {
- DataBufferFactory bufferFactory = response.bufferFactory();
- return bufferFactory.wrap(JSON.toJSONBytes(R.fail(HttpStatus.UNAUTHORIZED.value(), msg)));
- }));
+ if (value == null)
+ {
+ return;
+ }
+ String valueStr = value.toString();
+ String valueEncode = ServletUtils.urlEncode(valueStr);
+ mutate.header(name, valueEncode);
}
+ private Mono<Void> unauthorizedResponse(ServerWebExchange exchange, String msg)
+ {
+ log.error("[鉴权异常处理]请求路径:{}", exchange.getRequest().getPath());
+ return ServletUtils.webFluxResponseWriter(exchange.getResponse(), msg, HttpStatus.UNAUTHORIZED);
+ }
+
+ /**
+ * 获取缓存key
+ */
private String getTokenKey(String token)
{
return CacheConstants.LOGIN_TOKEN_KEY + token;
@@ -109,12 +112,8 @@
*/
private String getToken(ServerHttpRequest request)
{
- String token = request.getHeaders().getFirst(CacheConstants.HEADER);
- if (StringUtils.isNotEmpty(token) && token.startsWith(CacheConstants.TOKEN_PREFIX))
- {
- token = token.replace(CacheConstants.TOKEN_PREFIX, "");
- }
- return token;
+ String token = request.getHeaders().getFirst(CacheConstants.TOKEN_AUTHENTICATION);
+ return SecurityUtils.replaceTokenPrefix(token);
}
@Override
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java
index f613dea..9deab70 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/BlackListUrlFilter.java
@@ -5,11 +5,8 @@
import java.util.regex.Pattern;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
-import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
-import com.alibaba.fastjson.JSON;
-import com.ruoyi.common.core.web.domain.AjaxResult;
-import reactor.core.publisher.Mono;
+import com.ruoyi.common.core.utils.ServletUtils;
/**
* 黑名单过滤器
@@ -27,10 +24,7 @@
String url = exchange.getRequest().getURI().getPath();
if (config.matchBlacklist(url))
{
- ServerHttpResponse response = exchange.getResponse();
- response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
- return exchange.getResponse().writeWith(
- Mono.just(response.bufferFactory().wrap(JSON.toJSONBytes(AjaxResult.error("请求地址不允许访问")))));
+ return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求地址不允许访问");
}
return chain.filter(exchange);
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java
index 1e724f0..2c39abf 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/filter/ValidateCodeFilter.java
@@ -9,16 +9,13 @@
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
-import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
-import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
+import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
-import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.gateway.config.properties.CaptchaProperties;
import com.ruoyi.gateway.service.ValidateCodeService;
import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
/**
* 验证码过滤器
@@ -60,10 +57,7 @@
}
catch (Exception e)
{
- ServerHttpResponse response = exchange.getResponse();
- response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
- return exchange.getResponse().writeWith(
- Mono.just(response.bufferFactory().wrap(JSON.toJSONBytes(AjaxResult.error(e.getMessage())))));
+ return ServletUtils.webFluxResponseWriter(exchange.getResponse(), e.getMessage());
}
return chain.filter(exchange);
};
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java
index 0a8e44a..593e7e6 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/GatewayExceptionHandler.java
@@ -6,14 +6,10 @@
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
-import org.springframework.core.io.buffer.DataBufferFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
-import com.alibaba.fastjson.JSON;
-import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.ServletUtils;
import reactor.core.publisher.Mono;
/**
@@ -55,12 +51,6 @@
log.error("[网关异常处理]请求路径:{},异常信息:{}", exchange.getRequest().getPath(), ex.getMessage());
- response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
- response.setStatusCode(HttpStatus.OK);
-
- return response.writeWith(Mono.fromSupplier(() -> {
- DataBufferFactory bufferFactory = response.bufferFactory();
- return bufferFactory.wrap(JSON.toJSONBytes(R.fail(msg)));
- }));
+ return ServletUtils.webFluxResponseWriter(response, msg);
}
}
\ No newline at end of file
diff --git a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java
index 80c6460..c770a15 100644
--- a/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java
+++ b/ruoyi-gateway/src/main/java/com/ruoyi/gateway/handler/SentinelFallbackHandler.java
@@ -1,10 +1,8 @@
package com.ruoyi.gateway.handler;
-import java.nio.charset.StandardCharsets;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.slots.block.BlockException;
-import org.springframework.core.io.buffer.DataBuffer;
-import org.springframework.http.server.reactive.ServerHttpResponse;
+import com.ruoyi.common.core.utils.ServletUtils;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebExceptionHandler;
@@ -19,11 +17,7 @@
{
private Mono<Void> writeResponse(ServerResponse response, ServerWebExchange exchange)
{
- ServerHttpResponse serverHttpResponse = exchange.getResponse();
- serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
- byte[] datas = "{\"code\":429,\"msg\":\"请求超过最大数,请稍后再试\"}".getBytes(StandardCharsets.UTF_8);
- DataBuffer buffer = serverHttpResponse.bufferFactory().wrap(datas);
- return serverHttpResponse.writeWith(Mono.just(buffer));
+ return ServletUtils.webFluxResponseWriter(exchange.getResponse(), "请求超过最大数,请稍后再试");
}
@Override
diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js
index f60701e..ee01f9b 100644
--- a/ruoyi-ui/src/utils/ruoyi.js
+++ b/ruoyi-ui/src/utils/ruoyi.js
@@ -185,15 +185,15 @@
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof(value) !== "undefined") {
if (typeof value === 'object') {
- for (const key of Object.keys(value)) {
- let params = propName + '[' + key + ']';
- var subPart = encodeURIComponent(params) + "=";
- result += subPart + encodeURIComponent(value[key]) + "&";
- }
+ for (const key of Object.keys(value)) {
+ let params = propName + '[' + key + ']';
+ var subPart = encodeURIComponent(params) + "=";
+ result += subPart + encodeURIComponent(value[key]) + "&";
+ }
} else {
- result += part + encodeURIComponent(value) + "&";
- }
- }
+ result += part + encodeURIComponent(value) + "&";
+ }
+ }
}
- return result
+ return result
}
--
Gitblit v1.9.3