Browse Source

!383 优化 xss 的代码实现,独立 xss 包
Merge pull request !383 from 芋道源码/feature/dev-yunai

芋道源码 2 years ago
parent
commit
7d0e20be52

+ 2 - 46
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java

@@ -2,27 +2,18 @@ package cn.iocoder.yudao.framework.web.config;
 
 import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
-import cn.iocoder.yudao.framework.web.core.clean.JsoupXssCleaner;
-import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;
 import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
 import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
-import cn.iocoder.yudao.framework.web.core.filter.XssFilter;
 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
 import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
-import cn.iocoder.yudao.framework.web.core.json.XssStringJsonDeserializer;
 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
-import com.fasterxml.jackson.databind.ObjectMapper;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
 import org.springframework.util.AntPathMatcher;
-import org.springframework.util.PathMatcher;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.cors.CorsConfiguration;
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@@ -34,7 +25,7 @@ import javax.annotation.Resource;
 import javax.servlet.Filter;
 
 @AutoConfiguration
-@EnableConfigurationProperties({WebProperties.class, XssProperties.class})
+@EnableConfigurationProperties(WebProperties.class)
 public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
 
     @Resource
@@ -107,15 +98,6 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
         return createFilterBean(new CacheRequestBodyFilter(), WebFilterOrderEnum.REQUEST_BODY_CACHE_FILTER);
     }
 
-    /**
-     * 创建 XssFilter Bean,解决 Xss 安全问题
-     */
-    @Bean
-    @ConditionalOnBean(XssCleaner.class)
-    public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) {
-        return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER);
-    }
-
     /**
      * 创建 DemoFilter Bean,演示模式
      */
@@ -125,33 +107,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
         return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER);
     }
 
-
-    /**
-     * Xss 清理者
-     *
-     * @return XssCleaner
-     */
-    @Bean
-    @ConditionalOnMissingBean(XssCleaner.class)
-    public XssCleaner xssCleaner() {
-        return new JsoupXssCleaner();
-    }
-
-    /**
-     * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤
-     *
-     * @return Jackson2ObjectMapperBuilderCustomizer
-     */
-    @Bean
-    @ConditionalOnMissingBean(name = "xssJacksonCustomizer")
-    @ConditionalOnBean(ObjectMapper.class)
-    @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true")
-    public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) {
-        // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理
-        return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner));
-    }
-
-    private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
+    public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
         FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
         bean.setOrder(order);
         return bean;

+ 1 - 1
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java → yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.framework.web.config;
+package cn.iocoder.yudao.framework.xss.config;
 
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;

+ 60 - 0
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java

@@ -0,0 +1,60 @@
+package cn.iocoder.yudao.framework.xss.config;
+
+import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
+import cn.iocoder.yudao.framework.xss.core.clean.JsoupXssCleaner;
+import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
+import cn.iocoder.yudao.framework.xss.core.filter.XssFilter;
+import cn.iocoder.yudao.framework.xss.core.json.XssStringJsonDeserializer;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.util.PathMatcher;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.createFilterBean;
+
+@AutoConfiguration
+@EnableConfigurationProperties(XssProperties.class)
+public class YudaoXssAutoConfiguration implements WebMvcConfigurer {
+
+    /**
+     * Xss 清理者
+     *
+     * @return XssCleaner
+     */
+    @Bean
+    @ConditionalOnMissingBean(XssCleaner.class)
+    public XssCleaner xssCleaner() {
+        return new JsoupXssCleaner();
+    }
+
+    /**
+     * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤
+     *
+     * @return Jackson2ObjectMapperBuilderCustomizer
+     */
+    @Bean
+    @ConditionalOnMissingBean(name = "xssJacksonCustomizer")
+    @ConditionalOnBean(ObjectMapper.class)
+    @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true")
+    public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) {
+        // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理
+        return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner));
+    }
+
+    /**
+     * 创建 XssFilter Bean,解决 Xss 安全问题
+     */
+    @Bean
+    @ConditionalOnBean(XssCleaner.class)
+    public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) {
+        return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER);
+    }
+
+}

+ 2 - 18
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java → yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java

@@ -1,11 +1,11 @@
-package cn.iocoder.yudao.framework.web.core.clean;
+package cn.iocoder.yudao.framework.xss.core.clean;
 
 import org.jsoup.Jsoup;
 import org.jsoup.nodes.Document;
 import org.jsoup.safety.Safelist;
 
 /**
- * jsonp 过滤字符串
+ * 基于 JSONP 实现 XSS 过滤字符串
  */
 public class JsoupXssCleaner implements XssCleaner {
 
@@ -24,21 +24,6 @@ public class JsoupXssCleaner implements XssCleaner {
         this.baseUri = "";
     }
 
-    public JsoupXssCleaner(Safelist safelist) {
-        this.safelist = safelist;
-        this.baseUri = "";
-    }
-
-    public JsoupXssCleaner(String baseUri) {
-        this.safelist = buildSafelist();
-        this.baseUri = baseUri;
-    }
-
-    public JsoupXssCleaner(Safelist safelist, String baseUri) {
-        this.safelist = safelist;
-        this.baseUri = baseUri;
-    }
-
     /**
      * 构建一个 Xss 清理的 Safelist 规则。
      * 基于 Safelist#relaxed() 的基础上:
@@ -67,7 +52,6 @@ public class JsoupXssCleaner implements XssCleaner {
         // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径
         // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto");
         // WHITELIST.removeProtocols("img", "src", "http", "https");
-
         return relaxedSafelist;
     }
 

+ 2 - 1
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/xss/core/clean/XssCleaner.java

@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.framework.web.core.clean;
+package cn.iocoder.yudao.framework.xss.core.clean;
 
 /**
  * 对 html 文本中的有 Xss 风险的数据进行清理
@@ -12,4 +12,5 @@ public interface XssCleaner {
      * @return 清理后的 html
      */
     String clean(String html);
+
 }

+ 3 - 5
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java → yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java

@@ -1,7 +1,7 @@
-package cn.iocoder.yudao.framework.web.core.filter;
+package cn.iocoder.yudao.framework.xss.core.filter;
 
-import cn.iocoder.yudao.framework.web.config.XssProperties;
-import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;
+import cn.iocoder.yudao.framework.xss.config.XssProperties;
+import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
 import lombok.AllArgsConstructor;
 import org.springframework.util.PathMatcher;
 import org.springframework.web.filter.OncePerRequestFilter;
@@ -14,8 +14,6 @@ import java.io.IOException;
 
 /**
  * Xss 过滤器
- * <p>
- * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/
  *
  * @author 芋道源码
  */

+ 3 - 2
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java → yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java

@@ -1,6 +1,6 @@
-package cn.iocoder.yudao.framework.web.core.filter;
+package cn.iocoder.yudao.framework.xss.core.filter;
 
-import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;
+import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequestWrapper;
@@ -13,6 +13,7 @@ import java.util.Map;
  * @author 芋道源码
  */
 public class XssRequestWrapper extends HttpServletRequestWrapper {
+
     private final XssCleaner xssCleaner;
 
     public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) {

+ 2 - 2
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java → yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java

@@ -1,6 +1,6 @@
-package cn.iocoder.yudao.framework.web.core.json;
+package cn.iocoder.yudao.framework.xss.core.json;
 
-import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;
+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;

+ 6 - 0
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java

@@ -0,0 +1,6 @@
+/**
+ * 针对 XSS 的基础封装
+ *
+ * XSS 说明:https://tech.meituan.com/2018/09/27/fe-security.html
+ */
+package cn.iocoder.yudao.framework.xss;

+ 2 - 1
yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

@@ -1,4 +1,5 @@
 cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration
 cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration
 cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
-cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
+cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
+cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration