Commit 099754c26e9f1e0e460ddefd25609a73625d157f
1 parent
d7bec143
fix: xss 启用后编辑器上传图片错误
Showing
9 changed files
with
34 additions
and
81 deletions
yudao-dependencies/pom.xml
| ... | ... | @@ -396,11 +396,6 @@ |
| 396 | 396 | |
| 397 | 397 | <!-- 工具类相关 --> |
| 398 | 398 | <dependency> |
| 399 | - <groupId>org.jsoup</groupId> | |
| 400 | - <artifactId>jsoup</artifactId> | |
| 401 | - <version>${jsoup.version}</version> | |
| 402 | - </dependency> | |
| 403 | - <dependency> | |
| 404 | 399 | <groupId>cn.iocoder.boot</groupId> |
| 405 | 400 | <artifactId>yudao-common</artifactId> |
| 406 | 401 | <version>${revision}</version> |
| ... | ... | @@ -528,6 +523,12 @@ |
| 528 | 523 | <version>${ip2region.version}</version> |
| 529 | 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 | 533 | <dependency> |
| 533 | 534 | <groupId>com.squareup.okio</groupId> | ... | ... |
yudao-framework/yudao-common/pom.xml
yudao-framework/yudao-spring-boot-starter-web/pom.xml
| ... | ... | @@ -67,6 +67,11 @@ |
| 67 | 67 | <scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 --> |
| 68 | 68 | </dependency> |
| 69 | 69 | |
| 70 | + <!-- xss --> | |
| 71 | + <dependency> | |
| 72 | + <groupId>org.jsoup</groupId> | |
| 73 | + <artifactId>jsoup</artifactId> | |
| 74 | + </dependency> | |
| 70 | 75 | </dependencies> |
| 71 | 76 | |
| 72 | 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 | 131 | * |
| 132 | 132 | * @return XssCleaner |
| 133 | 133 | */ |
| 134 | - @ConditionalOnMissingBean(XssCleaner.class) | |
| 135 | 134 | @Bean |
| 135 | + @ConditionalOnMissingBean(XssCleaner.class) | |
| 136 | 136 | public XssCleaner xssCleaner() { |
| 137 | 137 | return new JsoupXssCleaner(); |
| 138 | 138 | } |
| ... | ... | @@ -145,12 +145,12 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { |
| 145 | 145 | @Bean |
| 146 | 146 | @ConditionalOnMissingBean(name = "xssJacksonCustomizer") |
| 147 | 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 | 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 | 154 | private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { |
| 155 | 155 | FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); |
| 156 | 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 | 4 | import org.jsoup.nodes.Document; |
| 5 | 5 | import org.jsoup.safety.Safelist; |
| 6 | 6 | |
| 7 | +/** | |
| 8 | + * jsonp 过滤字符串 | |
| 9 | + */ | |
| 7 | 10 | public class JsoupXssCleaner implements XssCleaner { |
| 8 | 11 | |
| 9 | 12 | private final Safelist safelist; |
| ... | ... | @@ -37,19 +40,15 @@ public class JsoupXssCleaner implements XssCleaner { |
| 37 | 40 | } |
| 38 | 41 | |
| 39 | 42 | /** |
| 40 | - * <p> | |
| 41 | 43 | * 构建一个 Xss 清理的 Safelist 规则。 |
| 42 | - * </p> | |
| 43 | - * | |
| 44 | - * <ul> | |
| 45 | 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 | 49 | * @return Safelist |
| 51 | 50 | */ |
| 52 | - protected Safelist buildSafelist() { | |
| 51 | + private Safelist buildSafelist() { | |
| 53 | 52 | // 使用 jsoup 提供的默认的 |
| 54 | 53 | Safelist relaxedSafelist = Safelist.relaxed(); |
| 55 | 54 | // 富文本编辑时一些样式是使用 style 来进行实现的 | ... | ... |
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java
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 | 20 | this.xssCleaner = xssCleaner; |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | + // ============================ parameter ============================ | |
| 23 | 24 | @Override |
| 24 | 25 | public Map<String, String[]> getParameterMap() { |
| 25 | 26 | Map<String, String[]> map = new LinkedHashMap<>(); |
| ... | ... | @@ -57,6 +58,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 57 | 58 | return xssCleaner.clean(value); |
| 58 | 59 | } |
| 59 | 60 | |
| 61 | + // ============================ attribute ============================ | |
| 60 | 62 | @Override |
| 61 | 63 | public Object getAttribute(String name) { |
| 62 | 64 | Object value = super.getAttribute(name); |
| ... | ... | @@ -66,6 +68,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 66 | 68 | return value; |
| 67 | 69 | } |
| 68 | 70 | |
| 71 | + // ============================ header ============================ | |
| 69 | 72 | @Override |
| 70 | 73 | public String getHeader(String name) { |
| 71 | 74 | String value = super.getHeader(name); |
| ... | ... | @@ -75,6 +78,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper { |
| 75 | 78 | return xssCleaner.clean(value); |
| 76 | 79 | } |
| 77 | 80 | |
| 81 | + // ============================ queryString ============================ | |
| 78 | 82 | @Override |
| 79 | 83 | public String getQueryString() { |
| 80 | 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 | 1 | package cn.iocoder.yudao.framework.web.core.json; |
| 2 | 2 | |
| 3 | -import cn.iocoder.yudao.framework.web.config.XssProperties; | |
| 4 | 3 | import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; |
| 5 | 4 | import com.fasterxml.jackson.core.JsonParser; |
| 6 | 5 | import com.fasterxml.jackson.core.JsonToken; |
| ... | ... | @@ -12,21 +11,21 @@ import lombok.extern.slf4j.Slf4j; |
| 12 | 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 | 19 | @Slf4j |
| 20 | 20 | @AllArgsConstructor |
| 21 | 21 | public class XssStringJsonDeserializer extends StringDeserializer { |
| 22 | 22 | |
| 23 | 23 | private final XssCleaner xssCleaner; |
| 24 | - private final XssProperties xssProperties; | |
| 25 | 24 | |
| 26 | 25 | @Override |
| 27 | 26 | public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { |
| 28 | 27 | if (p.hasToken(JsonToken.VALUE_STRING)) { |
| 29 | - return getCleanText(p.getText()); | |
| 28 | + return xssCleaner.clean(p.getText()); | |
| 30 | 29 | } |
| 31 | 30 | JsonToken t = p.currentToken(); |
| 32 | 31 | // [databind#381] |
| ... | ... | @@ -49,22 +48,12 @@ public class XssStringJsonDeserializer extends StringDeserializer { |
| 49 | 48 | if (t == JsonToken.START_OBJECT) { |
| 50 | 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 | 52 | if (t.isScalarValue()) { |
| 56 | 53 | String text = p.getValueAsString(); |
| 57 | - return getCleanText(text); | |
| 54 | + return xssCleaner.clean(text); | |
| 58 | 55 | } |
| 59 | 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 | - |