Commit 099754c26e9f1e0e460ddefd25609a73625d157f

Authored by gaibu
1 parent d7bec143

fix: xss 启用后编辑器上传图片错误

yudao-dependencies/pom.xml
@@ -396,11 +396,6 @@ @@ -396,11 +396,6 @@
396 396
397 <!-- 工具类相关 --> 397 <!-- 工具类相关 -->
398 <dependency> 398 <dependency>
399 - <groupId>org.jsoup</groupId>  
400 - <artifactId>jsoup</artifactId>  
401 - <version>${jsoup.version}</version>  
402 - </dependency>  
403 - <dependency>  
404 <groupId>cn.iocoder.boot</groupId> 399 <groupId>cn.iocoder.boot</groupId>
405 <artifactId>yudao-common</artifactId> 400 <artifactId>yudao-common</artifactId>
406 <version>${revision}</version> 401 <version>${revision}</version>
@@ -528,6 +523,12 @@ @@ -528,6 +523,12 @@
528 <version>${ip2region.version}</version> 523 <version>${ip2region.version}</version>
529 </dependency> 524 </dependency>
530 525
  526 + <dependency>
  527 + <groupId>org.jsoup</groupId>
  528 + <artifactId>jsoup</artifactId>
  529 + <version>${jsoup.version}</version>
  530 + </dependency>
  531 +
531 <!-- 三方云服务相关 --> 532 <!-- 三方云服务相关 -->
532 <dependency> 533 <dependency>
533 <groupId>com.squareup.okio</groupId> 534 <groupId>com.squareup.okio</groupId>
yudao-framework/yudao-common/pom.xml
@@ -133,10 +133,6 @@ @@ -133,10 +133,6 @@
133 <artifactId>transmittable-thread-local</artifactId> 133 <artifactId>transmittable-thread-local</artifactId>
134 </dependency> 134 </dependency>
135 135
136 - <dependency>  
137 - <groupId>org.jsoup</groupId>  
138 - <artifactId>jsoup</artifactId>  
139 - </dependency>  
140 </dependencies> 136 </dependencies>
141 137
142 </project> 138 </project>
yudao-framework/yudao-spring-boot-starter-web/pom.xml
@@ -67,6 +67,11 @@ @@ -67,6 +67,11 @@
67 <scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 --> 67 <scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 -->
68 </dependency> 68 </dependency>
69 69
  70 + <!-- xss -->
  71 + <dependency>
  72 + <groupId>org.jsoup</groupId>
  73 + <artifactId>jsoup</artifactId>
  74 + </dependency>
70 </dependencies> 75 </dependencies>
71 76
72 </project> 77 </project>
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 { @@ -131,8 +131,8 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
131 * 131 *
132 * @return XssCleaner 132 * @return XssCleaner
133 */ 133 */
134 - @ConditionalOnMissingBean(XssCleaner.class)  
135 @Bean 134 @Bean
  135 + @ConditionalOnMissingBean(XssCleaner.class)
136 public XssCleaner xssCleaner() { 136 public XssCleaner xssCleaner() {
137 return new JsoupXssCleaner(); 137 return new JsoupXssCleaner();
138 } 138 }
@@ -145,12 +145,12 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @@ -145,12 +145,12 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
145 @Bean 145 @Bean
146 @ConditionalOnMissingBean(name = "xssJacksonCustomizer") 146 @ConditionalOnMissingBean(name = "xssJacksonCustomizer")
147 @ConditionalOnBean(ObjectMapper.class) 147 @ConditionalOnBean(ObjectMapper.class)
148 - public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner, XssProperties xssProperties) { 148 + @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true")
  149 + public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) {
149 // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 150 // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理
150 - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner, xssProperties)); 151 + return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner));
151 } 152 }
152 153
153 -  
154 private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { 154 private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
155 FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); 155 FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
156 bean.setOrder(order); 156 bean.setOrder(order);
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; @@ -4,6 +4,9 @@ import org.jsoup.Jsoup;
4 import org.jsoup.nodes.Document; 4 import org.jsoup.nodes.Document;
5 import org.jsoup.safety.Safelist; 5 import org.jsoup.safety.Safelist;
6 6
  7 +/**
  8 + * jsonp 过滤字符串
  9 + */
7 public class JsoupXssCleaner implements XssCleaner { 10 public class JsoupXssCleaner implements XssCleaner {
8 11
9 private final Safelist safelist; 12 private final Safelist safelist;
@@ -37,19 +40,15 @@ public class JsoupXssCleaner implements XssCleaner { @@ -37,19 +40,15 @@ public class JsoupXssCleaner implements XssCleaner {
37 } 40 }
38 41
39 /** 42 /**
40 - * <p>  
41 * 构建一个 Xss 清理的 Safelist 规则。 43 * 构建一个 Xss 清理的 Safelist 规则。
42 - * </p>  
43 - *  
44 - * <ul>  
45 * 基于 Safelist#relaxed() 的基础上: 44 * 基于 Safelist#relaxed() 的基础上:
46 - * <li>扩展支持了 style 和 class 属性</li>  
47 - * <li>a 标签额外支持了 target 属性</li>  
48 - * <li>img 标签额外支持了 data 协议,便于支持 base64</li>  
49 - * </ul> 45 + * 1. 扩展支持了 style 和 class 属性
  46 + * 2. a 标签额外支持了 target 属性
  47 + * 3. img 标签额外支持了 data 协议,便于支持 base64
  48 + *
50 * @return Safelist 49 * @return Safelist
51 */ 50 */
52 - protected Safelist buildSafelist() { 51 + private Safelist buildSafelist() {
53 // 使用 jsoup 提供的默认的 52 // 使用 jsoup 提供的默认的
54 Safelist relaxedSafelist = Safelist.relaxed(); 53 Safelist relaxedSafelist = Safelist.relaxed();
55 // 富文本编辑时一些样式是使用 style 来进行实现的 54 // 富文本编辑时一些样式是使用 style 来进行实现的
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; @@ -4,6 +4,7 @@ package cn.iocoder.yudao.framework.web.core.clean;
4 * 对 html 文本中的有 Xss 风险的数据进行清理 4 * 对 html 文本中的有 Xss 风险的数据进行清理
5 */ 5 */
6 public interface XssCleaner { 6 public interface XssCleaner {
  7 +
7 /** 8 /**
8 * 清理有 Xss 风险的文本 9 * 清理有 Xss 风险的文本
9 * 10 *
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 { @@ -20,6 +20,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
20 this.xssCleaner = xssCleaner; 20 this.xssCleaner = xssCleaner;
21 } 21 }
22 22
  23 + // ============================ parameter ============================
23 @Override 24 @Override
24 public Map<String, String[]> getParameterMap() { 25 public Map<String, String[]> getParameterMap() {
25 Map<String, String[]> map = new LinkedHashMap<>(); 26 Map<String, String[]> map = new LinkedHashMap<>();
@@ -57,6 +58,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { @@ -57,6 +58,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
57 return xssCleaner.clean(value); 58 return xssCleaner.clean(value);
58 } 59 }
59 60
  61 + // ============================ attribute ============================
60 @Override 62 @Override
61 public Object getAttribute(String name) { 63 public Object getAttribute(String name) {
62 Object value = super.getAttribute(name); 64 Object value = super.getAttribute(name);
@@ -66,6 +68,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { @@ -66,6 +68,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
66 return value; 68 return value;
67 } 69 }
68 70
  71 + // ============================ header ============================
69 @Override 72 @Override
70 public String getHeader(String name) { 73 public String getHeader(String name) {
71 String value = super.getHeader(name); 74 String value = super.getHeader(name);
@@ -75,6 +78,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { @@ -75,6 +78,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
75 return xssCleaner.clean(value); 78 return xssCleaner.clean(value);
76 } 79 }
77 80
  81 + // ============================ queryString ============================
78 @Override 82 @Override
79 public String getQueryString() { 83 public String getQueryString() {
80 String value = super.getQueryString(); 84 String value = super.getQueryString();
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java
1 package cn.iocoder.yudao.framework.web.core.json; 1 package cn.iocoder.yudao.framework.web.core.json;
2 2
3 -import cn.iocoder.yudao.framework.web.config.XssProperties;  
4 import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; 3 import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;
5 import com.fasterxml.jackson.core.JsonParser; 4 import com.fasterxml.jackson.core.JsonParser;
6 import com.fasterxml.jackson.core.JsonToken; 5 import com.fasterxml.jackson.core.JsonToken;
@@ -12,21 +11,21 @@ import lombok.extern.slf4j.Slf4j; @@ -12,21 +11,21 @@ import lombok.extern.slf4j.Slf4j;
12 import java.io.IOException; 11 import java.io.IOException;
13 12
14 /** 13 /**
15 - * XSS过滤 jackson 反序列化器 14 + * XSS 过滤 jackson 反序列化器。
  15 + * 在反序列化的过程中,会对字符串进行 XSS 过滤。
16 * 16 *
17 - * 参考 ballcat 实现 17 + * @author Hccake
18 */ 18 */
19 @Slf4j 19 @Slf4j
20 @AllArgsConstructor 20 @AllArgsConstructor
21 public class XssStringJsonDeserializer extends StringDeserializer { 21 public class XssStringJsonDeserializer extends StringDeserializer {
22 22
23 private final XssCleaner xssCleaner; 23 private final XssCleaner xssCleaner;
24 - private final XssProperties xssProperties;  
25 24
26 @Override 25 @Override
27 public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { 26 public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
28 if (p.hasToken(JsonToken.VALUE_STRING)) { 27 if (p.hasToken(JsonToken.VALUE_STRING)) {
29 - return getCleanText(p.getText()); 28 + return xssCleaner.clean(p.getText());
30 } 29 }
31 JsonToken t = p.currentToken(); 30 JsonToken t = p.currentToken();
32 // [databind#381] 31 // [databind#381]
@@ -49,22 +48,12 @@ public class XssStringJsonDeserializer extends StringDeserializer { @@ -49,22 +48,12 @@ public class XssStringJsonDeserializer extends StringDeserializer {
49 if (t == JsonToken.START_OBJECT) { 48 if (t == JsonToken.START_OBJECT) {
50 return ctxt.extractScalarFromObject(p, this, _valueClass); 49 return ctxt.extractScalarFromObject(p, this, _valueClass);
51 } 50 }
52 - // allow coercions for other scalar types  
53 - // 17-Jan-2018, tatu: Related to [databind#1853] avoid FIELD_NAME by ensuring it's  
54 - // "real" scalar 51 +
55 if (t.isScalarValue()) { 52 if (t.isScalarValue()) {
56 String text = p.getValueAsString(); 53 String text = p.getValueAsString();
57 - return getCleanText(text); 54 + return xssCleaner.clean(text);
58 } 55 }
59 return (String) ctxt.handleUnexpectedToken(_valueClass, p); 56 return (String) ctxt.handleUnexpectedToken(_valueClass, p);
60 } 57 }
61 -  
62 - private String getCleanText(String text) {  
63 - if (text == null) {  
64 - return null;  
65 - }  
66 - return xssProperties.isEnable() ? xssCleaner.clean(text) : text;  
67 - }  
68 -  
69 } 58 }
70 59
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonSerializer.java deleted
1 -package cn.iocoder.yudao.framework.web.core.json;  
2 -  
3 -import cn.iocoder.yudao.framework.web.config.XssProperties;  
4 -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;  
5 -import com.fasterxml.jackson.core.JsonGenerator;  
6 -import com.fasterxml.jackson.databind.JsonSerializer;  
7 -import com.fasterxml.jackson.databind.SerializerProvider;  
8 -import lombok.AllArgsConstructor;  
9 -  
10 -import java.io.IOException;  
11 -  
12 -/**  
13 - * XSS过滤 jackson 序列化器  
14 - *  
15 - * 参考 ballcat 实现  
16 - */  
17 -@AllArgsConstructor  
18 -public class XssStringJsonSerializer extends JsonSerializer<String> {  
19 -  
20 - private final XssCleaner xssCleaner;  
21 - private final XssProperties xssProperties;  
22 -  
23 -  
24 - @Override  
25 - public Class<String> handledType() {  
26 - return String.class;  
27 - }  
28 -  
29 - @Override  
30 - public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)  
31 - throws IOException {  
32 - if (value != null) {  
33 - // 开启 Xss 才进行处理  
34 - if (xssProperties.isEnable()) {  
35 - value = xssCleaner.clean(value);  
36 - }  
37 - jsonGenerator.writeString(value);  
38 - }  
39 - }  
40 -  
41 -}  
42 -