fix: xss 启用后编辑器上传图片错误
This commit is contained in:
parent
d7bec143fd
commit
099754c26e
|
@ -395,11 +395,6 @@
|
|||
<!-- 工作流相关结束 -->
|
||||
|
||||
<!-- 工具类相关 -->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>${jsoup.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-common</artifactId>
|
||||
|
@ -528,6 +523,12 @@
|
|||
<version>${ip2region.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
<version>${jsoup.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 三方云服务相关 -->
|
||||
<dependency>
|
||||
<groupId>com.squareup.okio</groupId>
|
||||
|
|
|
@ -133,10 +133,6 @@
|
|||
<artifactId>transmittable-thread-local</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -67,6 +67,11 @@
|
|||
<scope>provided</scope> <!-- 设置为 provided,主要是 GlobalExceptionHandler 使用 -->
|
||||
</dependency>
|
||||
|
||||
<!-- xss -->
|
||||
<dependency>
|
||||
<groupId>org.jsoup</groupId>
|
||||
<artifactId>jsoup</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -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 <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
|
||||
FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
|
||||
bean.setOrder(order);
|
||||
|
|
|
@ -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 {
|
|||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 构建一个 Xss 清理的 Safelist 规则。
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* 基于 Safelist#relaxed() 的基础上:
|
||||
* <li>扩展支持了 style 和 class 属性</li>
|
||||
* <li>a 标签额外支持了 target 属性</li>
|
||||
* <li>img 标签额外支持了 data 协议,便于支持 base64</li>
|
||||
* </ul>
|
||||
* 1. 扩展支持了 style 和 class 属性
|
||||
* 2. a 标签额外支持了 target 属性
|
||||
* 3. img 标签额外支持了 data 协议,便于支持 base64
|
||||
*
|
||||
* @return Safelist
|
||||
*/
|
||||
protected Safelist buildSafelist() {
|
||||
private Safelist buildSafelist() {
|
||||
// 使用 jsoup 提供的默认的
|
||||
Safelist relaxedSafelist = Safelist.relaxed();
|
||||
// 富文本编辑时一些样式是使用 style 来进行实现的
|
||||
|
|
|
@ -4,6 +4,7 @@ package cn.iocoder.yudao.framework.web.core.clean;
|
|||
* 对 html 文本中的有 Xss 风险的数据进行清理
|
||||
*/
|
||||
public interface XssCleaner {
|
||||
|
||||
/**
|
||||
* 清理有 Xss 风险的文本
|
||||
*
|
||||
|
|
|
@ -20,6 +20,7 @@ public class XssRequestWrapper extends HttpServletRequestWrapper {
|
|||
this.xssCleaner = xssCleaner;
|
||||
}
|
||||
|
||||
// ============================ parameter ============================
|
||||
@Override
|
||||
public Map<String, String[]> getParameterMap() {
|
||||
Map<String, String[]> 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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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<String> {
|
||||
|
||||
private final XssCleaner xssCleaner;
|
||||
private final XssProperties xssProperties;
|
||||
|
||||
|
||||
@Override
|
||||
public Class<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue