From 79c51c6433eb3e1eacbc22002f07eb5f26fb5a06 Mon Sep 17 00:00:00 2001 From: E1 <876394202@qq.com> Date: Sun, 3 Mar 2024 10:26:28 +0000 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20Java21=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E4=B8=8Bdocker-compose=E4=B8=ADRedis=20Host=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E5=90=8D=E7=A7=B0=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: E1 <876394202@qq.com> --- script/docker/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/docker/docker-compose.yml b/script/docker/docker-compose.yml index e440d96c3..ae977dd97 100644 --- a/script/docker/docker-compose.yml +++ b/script/docker/docker-compose.yml @@ -50,7 +50,7 @@ services: --spring.datasource.dynamic.datasource.slave.url=${SLAVE_DATASOURCE_URL:-jdbc:mysql://yudao-mysql:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true} --spring.datasource.dynamic.datasource.slave.username=${SLAVE_DATASOURCE_USERNAME:-root} --spring.datasource.dynamic.datasource.slave.password=${SLAVE_DATASOURCE_PASSWORD:-123456} - --spring.redis.host=${REDIS_HOST:-yudao-redis} + --spring.data.redis.host=${REDIS_HOST:-yudao-redis} depends_on: - mysql - redis From c943233ee56d00d74d41a3fa8dbf85626f10cbdd Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 30 Mar 2024 17:39:56 +0800 Subject: [PATCH 2/2] =?UTF-8?q?bugfix=EF=BC=9A=E4=BF=AE=E5=A4=8D=20Xss=20?= =?UTF-8?q?=E5=BC=80=E5=90=AF=E6=97=B6=EF=BC=8C=E5=BF=BD=E7=95=A5=E7=9A=84?= =?UTF-8?q?=20URL=20=E9=92=88=E5=AF=B9=20RequestBody=20=E8=BF=98=E6=98=AF?= =?UTF-8?q?=E4=BC=9A=20XSS=20=E8=BF=87=E6=BB=A4=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xss/config/YudaoXssAutoConfiguration.java | 6 +++-- .../core/json/XssStringJsonDeserializer.java | 23 +++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java index 8cf5d5360..99b6a448f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java @@ -44,9 +44,11 @@ public class YudaoXssAutoConfiguration implements WebMvcConfigurer { @ConditionalOnMissingBean(name = "xssJacksonCustomizer") @ConditionalOnBean(ObjectMapper.class) @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") - public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) { + public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssProperties properties, + PathMatcher pathMatcher, + XssCleaner xssCleaner) { // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner)); + return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(properties, pathMatcher, xssCleaner)); } /** diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java index 2b1725d96..047b19d38 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java @@ -1,12 +1,16 @@ package cn.iocoder.yudao.framework.xss.core.json; +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; +import cn.iocoder.yudao.framework.xss.config.XssProperties; import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.deser.std.StringDeserializer; +import jakarta.servlet.http.HttpServletRequest; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.util.PathMatcher; import java.io.IOException; @@ -20,10 +24,29 @@ import java.io.IOException; @AllArgsConstructor public class XssStringJsonDeserializer extends StringDeserializer { + /** + * 属性 + */ + private final XssProperties properties; + /** + * 路径匹配器 + */ + private final PathMatcher pathMatcher; + private final XssCleaner xssCleaner; @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { + // 1. 白名单 URL 的处理 + HttpServletRequest request = ServletUtils.getRequest(); + if (request != null) { + String uri = ServletUtils.getRequest().getRequestURI(); + if (properties.getExcludeUrls().stream().anyMatch(excludeUrl -> pathMatcher.match(excludeUrl, uri))) { + return p.getText(); + } + } + + // 2. 真正使用 xssCleaner 进行过滤 if (p.hasToken(JsonToken.VALUE_STRING)) { return xssCleaner.clean(p.getText()); }