entry : sortParamsMap.entrySet()) {
+ queryString.append("&").append(entry.getKey()).append("=").append(entry.getValue());
+ }
+ return queryString.substring(1);
+ }
+
+ /**
+ * 获取请求体参数
+ *
+ * @param request request
+ * @return body
+ */
+ private String getRequestBody(HttpServletRequest request) {
+ CacheRequestBodyWrapper requestWrapper = new CacheRequestBodyWrapper(request);
+ // 获取 body
+ return new String(requestWrapper.getBody(), StandardCharsets.UTF_8);
+ }
+
+}
+
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java
new file mode 100644
index 000000000..d00fe7f8d
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java
@@ -0,0 +1,56 @@
+package cn.iocoder.yudao.framework.signature.core.redis;
+
+import lombok.AllArgsConstructor;
+import org.springframework.data.redis.core.StringRedisTemplate;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * API 签名 Redis DAO
+ *
+ * @author Zhougang
+ */
+@AllArgsConstructor
+public class SignatureRedisDAO {
+
+ private final StringRedisTemplate stringRedisTemplate;
+
+ /**
+ * 验签随机数
+ *
+ * KEY 格式:signature_nonce:%s // 参数为 随机数
+ * VALUE 格式:String
+ * 过期时间:不固定
+ */
+ private static final String SIGNATURE_NONCE = "signature_nonce:%s";
+
+ /**
+ * 签名密钥
+ *
+ * KEY 格式:signature_appid:%s // 参数为 appid
+ * VALUE 格式:String
+ * 过期时间:预加载到 redis 永不过期
+ */
+ private static final String SIGNATURE_APPID = "signature_appid:%s";
+
+ public String getAppSecret(String appId) {
+ return stringRedisTemplate.opsForValue().get(formatAppIdKey(appId));
+ }
+
+ public String getNonce(String nonce) {
+ return stringRedisTemplate.opsForValue().get(formatNonceKey(nonce));
+ }
+
+ public void setNonce(String nonce, long time, TimeUnit timeUnit) {
+ // 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 )
+ stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), nonce, time * 2, timeUnit);
+ }
+
+ private static String formatAppIdKey(String key) {
+ return String.format(SIGNATURE_APPID, key);
+ }
+
+ private static String formatNonceKey(String key) {
+ return String.format(SIGNATURE_NONCE, key);
+ }
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java b/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java
new file mode 100644
index 000000000..a253cd51a
--- /dev/null
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/test/java/cn/iocoder/yudao/framework/signature/core/SignatureTest.java
@@ -0,0 +1,136 @@
+package cn.iocoder.yudao.framework.signature.core;
+
+import cn.hutool.core.lang.Snowflake;
+import cn.hutool.crypto.digest.DigestUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import org.junit.jupiter.api.Test;
+
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * {@link SignatureTest} 的单元测试
+ */
+public class SignatureTest {
+
+ @Test
+ public void testSignatureGet() {
+ String appId = "xxxxxx";
+ Snowflake snowflake = new Snowflake();
+
+ // 验签请求头前端需传入字段
+ SortedMap headersMap = new TreeMap<>();
+ headersMap.put("appId", appId);
+ headersMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
+ headersMap.put("nonce", String.valueOf(snowflake.nextId()));
+
+ // 客户端加签内容
+ StringBuilder clientSignatureContent = new StringBuilder();
+ // 请求头
+ for (Map.Entry entry : headersMap.entrySet()) {
+ clientSignatureContent.append(entry.getKey()).append(entry.getValue());
+ }
+ // 请求 url
+ clientSignatureContent.append("/admin-api/infra/demo01-contact/get");
+ // 请求参数
+ SortedMap paramsMap = new TreeMap<>();
+ paramsMap.put("id", "100");
+ paramsMap.put("name", "张三");
+ StringBuilder queryString = new StringBuilder();
+ for (Map.Entry entry : paramsMap.entrySet()) {
+ queryString.append("&").append(entry.getKey()).append("=").append(entry.getValue());
+ }
+ clientSignatureContent.append(queryString.substring(1));
+ // 密钥
+ clientSignatureContent.append("d3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b");
+ System.out.println("加签内容:" + clientSignatureContent);
+ // 加签
+ headersMap.put("sign", DigestUtil.sha256Hex(clientSignatureContent.toString()));
+ headersMap.put("Authorization", "Bearer xxx");
+
+ HttpRequest get = HttpUtil.createGet("http://localhost:48080/admin-api/infra/demo01-contact/get?id=100&name=张三");
+ get.addHeaders(headersMap);
+ System.out.println("执行结果==" + get.execute());
+ }
+
+ @Test
+ public void testSignaturePost() {
+ String appId = "xxxxxx";
+ Snowflake snowflake = new Snowflake();
+
+ // 验签请求头前端需传入字段
+ SortedMap headersMap = new TreeMap<>();
+ headersMap.put("appId", appId);
+ headersMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
+ headersMap.put("nonce", String.valueOf(snowflake.nextId()));
+
+ // 客户端加签内容
+ StringBuilder clientSignatureContent = new StringBuilder();
+ // 请求头
+ for (Map.Entry entry : headersMap.entrySet()) {
+ clientSignatureContent.append(entry.getKey()).append(entry.getValue());
+ }
+ // 请求 url
+ clientSignatureContent.append("/admin-api/infra/demo01-contact/create");
+ // 请求体
+ String body = "{\n" +
+ " \"password\": \"1\",\n" +
+ " \"date\": \"2024-04-24 16:28:00\",\n" +
+ " \"user\": {\n" +
+ " \"area\": \"浦东新区\",\n" +
+ " \"1\": \"xx\",\n" +
+ " \"2\": \"xx\",\n" +
+ " \"province\": \"上海市\",\n" +
+ " \"data\": {\n" +
+ " \"99\": \"xx\",\n" +
+ " \"1\": \"xx\",\n" +
+ " \"100\": \"xx\",\n" +
+ " \"2\": \"xx\",\n" +
+ " \"3\": \"xx\",\n" +
+ " \"array\": [\n" +
+ " {\n" +
+ " \"3\": \"aa\",\n" +
+ " \"4\": \"aa\",\n" +
+ " \"2\": \"aa\",\n" +
+ " \"1\": \"aa\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"99\": \"aa\",\n" +
+ " \"100\": \"aa\",\n" +
+ " \"88\": \"aa\",\n" +
+ " \"120\": \"aa\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"sex\": \"男\",\n" +
+ " \"name\": \"张三\",\n" +
+ " \"array\": [\n" +
+ " \"1\",\n" +
+ " \"3\",\n" +
+ " \"5\",\n" +
+ " \"2\"\n" +
+ " ]\n" +
+ " },\n" +
+ " \"username\": \"xiaoming\"\n" +
+ "}";
+ clientSignatureContent.append(body);
+
+ // 密钥
+ clientSignatureContent.append("d3cbeed9baf4e68673a1f69a2445359a20022b7c28ea2933dd9db9f3a29f902b");
+ System.out.println("加签内容:" + clientSignatureContent);
+ // 加签
+ headersMap.put("sign", DigestUtil.sha256Hex(clientSignatureContent.toString()));
+ headersMap.put("Authorization", "Bearer xxx");
+
+ HttpRequest post = HttpUtil.createPost("http://localhost:48080/admin-api/infra/demo01-contact/create");
+ post.addHeaders(headersMap);
+ post.body(body);
+ try (HttpResponse execute = post.execute()) {
+ System.out.println("执行结果==" + execute);
+ }
+ }
+
+}
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
index 8e80fa591..e181edeb4 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
@@ -23,6 +23,10 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper {
*/
private final byte[] body;
+ public byte[] getBody() {
+ return body;
+ }
+
public CacheRequestBodyWrapper(HttpServletRequest request) {
super(request);
body = ServletUtils.getBodyBytes(request);
From 5bc01901948de01ef94d6186389a566aa6b44858 Mon Sep 17 00:00:00 2001
From: zhougang <921366807@qq.com>
Date: Sun, 19 May 2024 15:39:22 +0800
Subject: [PATCH 2/3] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91=20?=
=?UTF-8?q?=E6=A0=BC=E5=BC=8F=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
yudao-framework/yudao-spring-boot-starter-protection/pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml
index 025bb7591..46326c63a 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/pom.xml
+++ b/yudao-framework/yudao-spring-boot-starter-protection/pom.xml
@@ -12,7 +12,7 @@
jar
${project.artifactId}
- 服务保证,提供分布式锁、幂等、限流、熔断、API签名等等功能
+ 服务保证,提供分布式锁、幂等、限流、熔断、API 签名等等功能
https://github.com/YunaiV/ruoyi-vue-pro
From 5f278ac23b392d6ecd9452cc50fdfc9e77af97e8 Mon Sep 17 00:00:00 2001
From: zhougang
Date: Tue, 28 May 2024 15:09:01 +0800
Subject: [PATCH 3/3] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=E9=83=A8=E5=88=86=E4=BB=A3=E7=A0=81=E9=A3=8E?=
=?UTF-8?q?=E6=A0=BC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../{Signature.java => ApiSignature.java} | 16 ++++---
.../signature/core/aop/SignatureAspect.java | 43 ++++++-------------
.../core/redis/SignatureRedisDAO.java | 3 +-
...ot.autoconfigure.AutoConfiguration.imports | 3 +-
.../core/filter/CacheRequestBodyWrapper.java | 4 --
5 files changed, 26 insertions(+), 43 deletions(-)
rename yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/{Signature.java => ApiSignature.java} (75%)
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/ApiSignature.java
similarity index 75%
rename from yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java
rename to yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/ApiSignature.java
index 1b7e12786..e338ae709 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/Signature.java
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/annotation/ApiSignature.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.framework.signature.core.annotation;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import java.lang.annotation.*;
+import java.util.concurrent.TimeUnit;
/**
@@ -14,12 +15,17 @@ import java.lang.annotation.*;
@Documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
-public @interface Signature {
+public @interface ApiSignature {
/**
- * 同一个请求多长时间内有效 默认 10分钟
+ * 同一个请求多长时间内有效 默认 60 秒
*/
- long expireTime() default 600000L;
+ int timeout() default 60;
+
+ /**
+ * 时间单位,默认为 SECONDS 秒
+ */
+ TimeUnit timeUnit() default TimeUnit.SECONDS;
// ========================== 签名参数 ==========================
@@ -50,8 +56,4 @@ public @interface Signature {
*/
String sign() default "sign";
- /**
- * url 客户端不需要传递,但是可以用来加签(如: /{id} 带有动态参数的 url ,如果没有动态参数可设置为 false 不进行加签)
- */
- boolean urlEnable() default true;
}
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java
index dc1510465..a001419f8 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/aop/SignatureAspect.java
@@ -1,12 +1,13 @@
package cn.iocoder.yudao.framework.signature.core.aop;
import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SignUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
-import cn.iocoder.yudao.framework.signature.core.annotation.Signature;
+import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
import cn.iocoder.yudao.framework.signature.core.redis.SignatureRedisDAO;
import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyWrapper;
import jakarta.servlet.http.HttpServletRequest;
@@ -15,7 +16,6 @@ import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
-import org.springframework.util.Assert;
import java.nio.charset.StandardCharsets;
import java.util.Map;
@@ -25,7 +25,7 @@ import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
/**
- * 拦截声明了 {@link Signature} 注解的方法,实现签名
+ * 拦截声明了 {@link ApiSignature} 注解的方法,实现签名
*
* @author Zhougang
*/
@@ -37,9 +37,9 @@ public class SignatureAspect {
private final SignatureRedisDAO signatureRedisDAO;
@Before("@annotation(signature)")
- public void beforePointCut(JoinPoint joinPoint, Signature signature) {
+ public void beforePointCut(JoinPoint joinPoint, ApiSignature signature) {
if (!verifySignature(signature, Objects.requireNonNull(ServletUtils.getRequest()))) {
- log.info("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(),
+ log.error("[beforePointCut][方法{} 参数({}) 签名失败]", joinPoint.getSignature().toString(),
joinPoint.getArgs());
String message = StrUtil.blankToDefault(signature.message(),
GlobalErrorCodeConstants.BAD_REQUEST.getMsg());
@@ -47,25 +47,22 @@ public class SignatureAspect {
}
}
- private boolean verifySignature(Signature signature, HttpServletRequest request) {
+ private boolean verifySignature(ApiSignature signature, HttpServletRequest request) {
if (!verifyHeaders(signature, request)) {
return false;
}
// 校验 appId 是否能获取到对应的 appSecret
String appId = request.getHeader(signature.appId());
String appSecret = signatureRedisDAO.getAppSecret(appId);
- Assert.notNull(appSecret, "找不到对应的 appSecret");
+ Assert.notNull(appSecret, "[appId({})] 找不到对应的 appSecret", appId);
// 请求头
SortedMap headersMap = getRequestHeaders(signature, request);
- // 如:/user/{id} url 带有动态参数的情况
- String urlParams = signature.urlEnable() ? request.getServletPath() : "";
// 请求参数
String requestParams = getRequestParams(request);
// 请求体
- String requestBody = getRequestBody(request);
+ String requestBody = ServletUtils.isJsonRequest(request) ? ServletUtils.getBody(request) : "";
// 生成服务端签名
- String serverSignature = SignUtil.signParamsSha256(headersMap,
- urlParams + requestParams + requestBody + appSecret);
+ String serverSignature = SignUtil.signParamsSha256(headersMap, requestParams + requestBody + appSecret);
// 客户端签名
String clientSignature = request.getHeader(signature.sign());
if (!StrUtil.equals(clientSignature, serverSignature)) {
@@ -73,7 +70,7 @@ public class SignatureAspect {
}
String nonce = headersMap.get(signature.nonce());
// 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 )
- signatureRedisDAO.setNonce(nonce, signature.expireTime(), TimeUnit.MILLISECONDS);
+ signatureRedisDAO.setNonce(nonce, signature.timeout() * 2L, signature.timeUnit());
return true;
}
@@ -87,7 +84,7 @@ public class SignatureAspect {
* @param signature signature
* @param request request
*/
- private boolean verifyHeaders(Signature signature, HttpServletRequest request) {
+ private boolean verifyHeaders(ApiSignature signature, HttpServletRequest request) {
String appId = request.getHeader(signature.appId());
if (StrUtil.isBlank(appId)) {
return false;
@@ -97,7 +94,7 @@ public class SignatureAspect {
return false;
}
String nonce = request.getHeader(signature.nonce());
- if (StrUtil.isBlank(nonce) || nonce.length() < 10) {
+ if (StrUtil.isBlank(nonce) || StrUtil.length(nonce) < 10) {
return false;
}
String sign = request.getHeader(signature.sign());
@@ -105,7 +102,7 @@ public class SignatureAspect {
return false;
}
// 其他合法性校验
- long expireTime = signature.expireTime();
+ long expireTime = signature.timeUnit().toMillis(signature.timeout());
long requestTimestamp = Long.parseLong(timestamp);
// 检查 timestamp 是否超出允许的范围 (重点一:此处需要取绝对值)
long timestampDisparity = Math.abs(System.currentTimeMillis() - requestTimestamp);
@@ -122,7 +119,7 @@ public class SignatureAspect {
* @param request request
* @return signature params
*/
- private SortedMap getRequestHeaders(Signature signature, HttpServletRequest request) {
+ private SortedMap getRequestHeaders(ApiSignature signature, HttpServletRequest request) {
SortedMap sortedMap = new TreeMap<>();
sortedMap.put(signature.appId(), request.getHeader(signature.appId()));
sortedMap.put(signature.timestamp(), request.getHeader(signature.timestamp()));
@@ -154,17 +151,5 @@ public class SignatureAspect {
return queryString.substring(1);
}
- /**
- * 获取请求体参数
- *
- * @param request request
- * @return body
- */
- private String getRequestBody(HttpServletRequest request) {
- CacheRequestBodyWrapper requestWrapper = new CacheRequestBodyWrapper(request);
- // 获取 body
- return new String(requestWrapper.getBody(), StandardCharsets.UTF_8);
- }
-
}
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java
index d00fe7f8d..326e238ee 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/java/cn/iocoder/yudao/framework/signature/core/redis/SignatureRedisDAO.java
@@ -42,8 +42,7 @@ public class SignatureRedisDAO {
}
public void setNonce(String nonce, long time, TimeUnit timeUnit) {
- // 将 nonce 记入缓存,防止重复使用(重点二:此处需要将 ttl 设定为允许 timestamp 时间差的值 x 2 )
- stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), nonce, time * 2, timeUnit);
+ stringRedisTemplate.opsForValue().set(formatNonceKey(nonce), nonce, time, timeUnit);
}
private static String formatAppIdKey(String key) {
diff --git a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
index d7cd3a883..6cab74e75 100644
--- a/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
+++ b/yudao-framework/yudao-spring-boot-starter-protection/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -1,3 +1,4 @@
cn.iocoder.yudao.framework.idempotent.config.YudaoIdempotentConfiguration
cn.iocoder.yudao.framework.lock4j.config.YudaoLock4jConfiguration
-cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration
\ No newline at end of file
+cn.iocoder.yudao.framework.ratelimiter.config.YudaoRateLimiterConfiguration
+cn.iocoder.yudao.framework.signature.config.YudaoSignatureAutoConfiguration
\ No newline at end of file
diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
index e181edeb4..8e80fa591 100644
--- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
+++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyWrapper.java
@@ -23,10 +23,6 @@ public class CacheRequestBodyWrapper extends HttpServletRequestWrapper {
*/
private final byte[] body;
- public byte[] getBody() {
- return body;
- }
-
public CacheRequestBodyWrapper(HttpServletRequest request) {
super(request);
body = ServletUtils.getBodyBytes(request);