diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index cc23f245c..22cb6da5c 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -395,11 +395,6 @@ - - org.jsoup - jsoup - ${jsoup.version} - cn.iocoder.boot yudao-common @@ -528,6 +523,12 @@ ${ip2region.version} + + org.jsoup + jsoup + ${jsoup.version} + + com.squareup.okio diff --git a/yudao-framework/yudao-common/pom.xml b/yudao-framework/yudao-common/pom.xml index a732967f2..2ad12ad87 100644 --- a/yudao-framework/yudao-common/pom.xml +++ b/yudao-framework/yudao-common/pom.xml @@ -133,10 +133,6 @@ transmittable-thread-local - - org.jsoup - jsoup - diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml index 8662584e3..7d277790c 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml @@ -67,6 +67,11 @@ provided + + + org.jsoup + jsoup + diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 50586d4a6..95955d5ee 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java @@ -131,8 +131,8 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { * * @return XssCleaner */ - @ConditionalOnMissingBean(XssCleaner.class) @Bean + @ConditionalOnMissingBean(XssCleaner.class) public XssCleaner xssCleaner() { return new JsoupXssCleaner(); } @@ -145,12 +145,12 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @Bean @ConditionalOnMissingBean(name = "xssJacksonCustomizer") @ConditionalOnBean(ObjectMapper.class) - public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner, XssProperties xssProperties) { + @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") + public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) { // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner, xssProperties)); + return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner)); } - private static FilterRegistrationBean createFilterBean(T filter, Integer order) { FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); bean.setOrder(order); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java index 5a72834af..559267c3f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java @@ -4,6 +4,9 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.safety.Safelist; +/** + * jsonp 过滤字符串 + */ public class JsoupXssCleaner implements XssCleaner { private final Safelist safelist; @@ -37,19 +40,15 @@ public class JsoupXssCleaner implements XssCleaner { } /** - *

* 构建一个 Xss 清理的 Safelist 规则。 - *

- * - *
    * 基于 Safelist#relaxed() 的基础上: - *
  • 扩展支持了 style 和 class 属性
  • - *
  • a 标签额外支持了 target 属性
  • - *
  • img 标签额外支持了 data 协议,便于支持 base64
  • - *
+ * 1. 扩展支持了 style 和 class 属性 + * 2. a 标签额外支持了 target 属性 + * 3. img 标签额外支持了 data 协议,便于支持 base64 + * * @return Safelist */ - protected Safelist buildSafelist() { + private Safelist buildSafelist() { // 使用 jsoup 提供的默认的 Safelist relaxedSafelist = Safelist.relaxed(); // 富文本编辑时一些样式是使用 style 来进行实现的 diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java index a5ecc1bcc..433f7e775 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java @@ -4,6 +4,7 @@ package cn.iocoder.yudao.framework.web.core.clean; * 对 html 文本中的有 Xss 风险的数据进行清理 */ public interface XssCleaner { + /** * 清理有 Xss 风险的文本 * diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java index 1724cb163..7beed46cc 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java @@ -20,6 +20,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { this.xssCleaner = xssCleaner; } + // ============================ parameter ============================ @Override public Map getParameterMap() { Map map = new LinkedHashMap<>(); @@ -57,6 +58,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { return xssCleaner.clean(value); } + // ============================ attribute ============================ @Override public Object getAttribute(String name) { Object value = super.getAttribute(name); @@ -66,6 +68,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { return value; } + // ============================ header ============================ @Override public String getHeader(String name) { String value = super.getHeader(name); @@ -75,6 +78,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { return xssCleaner.clean(value); } + // ============================ queryString ============================ @Override public String getQueryString() { String value = super.getQueryString(); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java index 185469be5..7e1f631c7 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.framework.web.core.json; -import cn.iocoder.yudao.framework.web.config.XssProperties; import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; @@ -12,21 +11,21 @@ import lombok.extern.slf4j.Slf4j; import java.io.IOException; /** - * XSS过滤 jackson 反序列化器 + * XSS 过滤 jackson 反序列化器。 + * 在反序列化的过程中,会对字符串进行 XSS 过滤。 * - * 参考 ballcat 实现 + * @author Hccake */ @Slf4j @AllArgsConstructor public class XssStringJsonDeserializer extends StringDeserializer { private final XssCleaner xssCleaner; - private final XssProperties xssProperties; @Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { if (p.hasToken(JsonToken.VALUE_STRING)) { - return getCleanText(p.getText()); + return xssCleaner.clean(p.getText()); } JsonToken t = p.currentToken(); // [databind#381] @@ -49,22 +48,12 @@ public class XssStringJsonDeserializer extends StringDeserializer { if (t == JsonToken.START_OBJECT) { return ctxt.extractScalarFromObject(p, this, _valueClass); } - // allow coercions for other scalar types - // 17-Jan-2018, tatu: Related to [databind#1853] avoid FIELD_NAME by ensuring it's - // "real" scalar + if (t.isScalarValue()) { String text = p.getValueAsString(); - return getCleanText(text); + return xssCleaner.clean(text); } return (String) ctxt.handleUnexpectedToken(_valueClass, p); } - - private String getCleanText(String text) { - if (text == null) { - return null; - } - return xssProperties.isEnable() ? xssCleaner.clean(text) : text; - } - } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonSerializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonSerializer.java deleted file mode 100644 index 261c99ffe..000000000 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonSerializer.java +++ /dev/null @@ -1,42 +0,0 @@ -package cn.iocoder.yudao.framework.web.core.json; - -import cn.iocoder.yudao.framework.web.config.XssProperties; -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.databind.JsonSerializer; -import com.fasterxml.jackson.databind.SerializerProvider; -import lombok.AllArgsConstructor; - -import java.io.IOException; - -/** - * XSS过滤 jackson 序列化器 - * - * 参考 ballcat 实现 - */ -@AllArgsConstructor -public class XssStringJsonSerializer extends JsonSerializer { - - private final XssCleaner xssCleaner; - private final XssProperties xssProperties; - - - @Override - public Class handledType() { - return String.class; - } - - @Override - public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) - throws IOException { - if (value != null) { - // 开启 Xss 才进行处理 - if (xssProperties.isEnable()) { - value = xssCleaner.clean(value); - } - jsonGenerator.writeString(value); - } - } - -} -