Commit 7d0e20be524a78861f9640eef45554bfb782774f

Authored by 芋道源码
Committed by Gitee
2 parents 3622b7f3 179fdc84

!383 优化 xss 的代码实现,独立 xss 包

Merge pull request !383 from 芋道源码/feature/dev-yunai
Showing 10 changed files with 83 additions and 76 deletions
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; @@ -2,27 +2,18 @@ package cn.iocoder.yudao.framework.web.config;
2 2
3 import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; 3 import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
4 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; 4 import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
5 -import cn.iocoder.yudao.framework.web.core.clean.JsoupXssCleaner;  
6 -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner;  
7 import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter; 5 import cn.iocoder.yudao.framework.web.core.filter.CacheRequestBodyFilter;
8 import cn.iocoder.yudao.framework.web.core.filter.DemoFilter; 6 import cn.iocoder.yudao.framework.web.core.filter.DemoFilter;
9 -import cn.iocoder.yudao.framework.web.core.filter.XssFilter;  
10 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; 7 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
11 import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler; 8 import cn.iocoder.yudao.framework.web.core.handler.GlobalResponseBodyHandler;
12 -import cn.iocoder.yudao.framework.web.core.json.XssStringJsonDeserializer;  
13 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; 9 import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
14 -import com.fasterxml.jackson.databind.ObjectMapper;  
15 import org.springframework.beans.factory.annotation.Value; 10 import org.springframework.beans.factory.annotation.Value;
16 import org.springframework.boot.autoconfigure.AutoConfiguration; 11 import org.springframework.boot.autoconfigure.AutoConfiguration;
17 -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;  
18 -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;  
19 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; 12 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
20 -import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;  
21 import org.springframework.boot.context.properties.EnableConfigurationProperties; 13 import org.springframework.boot.context.properties.EnableConfigurationProperties;
22 import org.springframework.boot.web.servlet.FilterRegistrationBean; 14 import org.springframework.boot.web.servlet.FilterRegistrationBean;
23 import org.springframework.context.annotation.Bean; 15 import org.springframework.context.annotation.Bean;
24 import org.springframework.util.AntPathMatcher; 16 import org.springframework.util.AntPathMatcher;
25 -import org.springframework.util.PathMatcher;  
26 import org.springframework.web.bind.annotation.RestController; 17 import org.springframework.web.bind.annotation.RestController;
27 import org.springframework.web.cors.CorsConfiguration; 18 import org.springframework.web.cors.CorsConfiguration;
28 import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 19 import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
@@ -34,7 +25,7 @@ import javax.annotation.Resource; @@ -34,7 +25,7 @@ import javax.annotation.Resource;
34 import javax.servlet.Filter; 25 import javax.servlet.Filter;
35 26
36 @AutoConfiguration 27 @AutoConfiguration
37 -@EnableConfigurationProperties({WebProperties.class, XssProperties.class}) 28 +@EnableConfigurationProperties(WebProperties.class)
38 public class YudaoWebAutoConfiguration implements WebMvcConfigurer { 29 public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
39 30
40 @Resource 31 @Resource
@@ -108,15 +99,6 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @@ -108,15 +99,6 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
108 } 99 }
109 100
110 /** 101 /**
111 - * 创建 XssFilter Bean,解决 Xss 安全问题  
112 - */  
113 - @Bean  
114 - @ConditionalOnBean(XssCleaner.class)  
115 - public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) {  
116 - return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER);  
117 - }  
118 -  
119 - /**  
120 * 创建 DemoFilter Bean,演示模式 102 * 创建 DemoFilter Bean,演示模式
121 */ 103 */
122 @Bean 104 @Bean
@@ -125,33 +107,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @@ -125,33 +107,7 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
125 return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER); 107 return createFilterBean(new DemoFilter(), WebFilterOrderEnum.DEMO_FILTER);
126 } 108 }
127 109
128 -  
129 - /**  
130 - * Xss 清理者  
131 - *  
132 - * @return XssCleaner  
133 - */  
134 - @Bean  
135 - @ConditionalOnMissingBean(XssCleaner.class)  
136 - public XssCleaner xssCleaner() {  
137 - return new JsoupXssCleaner();  
138 - }  
139 -  
140 - /**  
141 - * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤  
142 - *  
143 - * @return Jackson2ObjectMapperBuilderCustomizer  
144 - */  
145 - @Bean  
146 - @ConditionalOnMissingBean(name = "xssJacksonCustomizer")  
147 - @ConditionalOnBean(ObjectMapper.class)  
148 - @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true")  
149 - public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) {  
150 - // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理  
151 - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner));  
152 - }  
153 -  
154 - private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) { 110 + public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
155 FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter); 111 FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
156 bean.setOrder(order); 112 bean.setOrder(order);
157 return bean; 113 return bean;
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java
1 -package cn.iocoder.yudao.framework.web.config; 1 +package cn.iocoder.yudao.framework.xss.config;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import org.springframework.boot.context.properties.ConfigurationProperties; 4 import org.springframework.boot.context.properties.ConfigurationProperties;
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.xss.config;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
  4 +import cn.iocoder.yudao.framework.xss.core.clean.JsoupXssCleaner;
  5 +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
  6 +import cn.iocoder.yudao.framework.xss.core.filter.XssFilter;
  7 +import cn.iocoder.yudao.framework.xss.core.json.XssStringJsonDeserializer;
  8 +import com.fasterxml.jackson.databind.ObjectMapper;
  9 +import org.springframework.boot.autoconfigure.AutoConfiguration;
  10 +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
  11 +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
  12 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  13 +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
  14 +import org.springframework.boot.context.properties.EnableConfigurationProperties;
  15 +import org.springframework.boot.web.servlet.FilterRegistrationBean;
  16 +import org.springframework.context.annotation.Bean;
  17 +import org.springframework.util.PathMatcher;
  18 +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
  19 +
  20 +import static cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration.createFilterBean;
  21 +
  22 +@AutoConfiguration
  23 +@EnableConfigurationProperties(XssProperties.class)
  24 +public class YudaoXssAutoConfiguration implements WebMvcConfigurer {
  25 +
  26 + /**
  27 + * Xss 清理者
  28 + *
  29 + * @return XssCleaner
  30 + */
  31 + @Bean
  32 + @ConditionalOnMissingBean(XssCleaner.class)
  33 + public XssCleaner xssCleaner() {
  34 + return new JsoupXssCleaner();
  35 + }
  36 +
  37 + /**
  38 + * 注册 Jackson 的序列化器,用于处理 json 类型参数的 xss 过滤
  39 + *
  40 + * @return Jackson2ObjectMapperBuilderCustomizer
  41 + */
  42 + @Bean
  43 + @ConditionalOnMissingBean(name = "xssJacksonCustomizer")
  44 + @ConditionalOnBean(ObjectMapper.class)
  45 + @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true")
  46 + public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssCleaner xssCleaner) {
  47 + // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理
  48 + return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(xssCleaner));
  49 + }
  50 +
  51 + /**
  52 + * 创建 XssFilter Bean,解决 Xss 安全问题
  53 + */
  54 + @Bean
  55 + @ConditionalOnBean(XssCleaner.class)
  56 + public FilterRegistrationBean<XssFilter> xssFilter(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) {
  57 + return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER);
  58 + }
  59 +
  60 +}
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java
1 -package cn.iocoder.yudao.framework.web.core.clean; 1 +package cn.iocoder.yudao.framework.xss.core.clean;
2 2
3 import org.jsoup.Jsoup; 3 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 /** 7 /**
8 - * jsonp 过滤字符串 8 + * 基于 JSONP 实现 XSS 过滤字符串
9 */ 9 */
10 public class JsoupXssCleaner implements XssCleaner { 10 public class JsoupXssCleaner implements XssCleaner {
11 11
@@ -24,21 +24,6 @@ public class JsoupXssCleaner implements XssCleaner { @@ -24,21 +24,6 @@ public class JsoupXssCleaner implements XssCleaner {
24 this.baseUri = ""; 24 this.baseUri = "";
25 } 25 }
26 26
27 - public JsoupXssCleaner(Safelist safelist) {  
28 - this.safelist = safelist;  
29 - this.baseUri = "";  
30 - }  
31 -  
32 - public JsoupXssCleaner(String baseUri) {  
33 - this.safelist = buildSafelist();  
34 - this.baseUri = baseUri;  
35 - }  
36 -  
37 - public JsoupXssCleaner(Safelist safelist, String baseUri) {  
38 - this.safelist = safelist;  
39 - this.baseUri = baseUri;  
40 - }  
41 -  
42 /** 27 /**
43 * 构建一个 Xss 清理的 Safelist 规则。 28 * 构建一个 Xss 清理的 Safelist 规则。
44 * 基于 Safelist#relaxed() 的基础上: 29 * 基于 Safelist#relaxed() 的基础上:
@@ -67,7 +52,6 @@ public class JsoupXssCleaner implements XssCleaner { @@ -67,7 +52,6 @@ public class JsoupXssCleaner implements XssCleaner {
67 // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径 52 // 虽然可以重写 WhiteList#isSafeAttribute 来处理,但是有隐患,所以暂时不支持相对路径
68 // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto"); 53 // WHITELIST.removeProtocols("a", "href", "ftp", "http", "https", "mailto");
69 // WHITELIST.removeProtocols("img", "src", "http", "https"); 54 // WHITELIST.removeProtocols("img", "src", "http", "https");
70 -  
71 return relaxedSafelist; 55 return relaxedSafelist;
72 } 56 }
73 57
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java
1 -package cn.iocoder.yudao.framework.web.core.clean; 1 +package cn.iocoder.yudao.framework.xss.core.clean;
2 2
3 /** 3 /**
4 * 对 html 文本中的有 Xss 风险的数据进行清理 4 * 对 html 文本中的有 Xss 风险的数据进行清理
@@ -12,4 +12,5 @@ public interface XssCleaner { @@ -12,4 +12,5 @@ public interface XssCleaner {
12 * @return 清理后的 html 12 * @return 清理后的 html
13 */ 13 */
14 String clean(String html); 14 String clean(String html);
  15 +
15 } 16 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java
1 -package cn.iocoder.yudao.framework.web.core.filter; 1 +package cn.iocoder.yudao.framework.xss.core.filter;
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.xss.config.XssProperties;
  4 +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
5 import lombok.AllArgsConstructor; 5 import lombok.AllArgsConstructor;
6 import org.springframework.util.PathMatcher; 6 import org.springframework.util.PathMatcher;
7 import org.springframework.web.filter.OncePerRequestFilter; 7 import org.springframework.web.filter.OncePerRequestFilter;
@@ -14,8 +14,6 @@ import java.io.IOException; @@ -14,8 +14,6 @@ import java.io.IOException;
14 14
15 /** 15 /**
16 * Xss 过滤器 16 * Xss 过滤器
17 - * <p>  
18 - * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/  
19 * 17 *
20 * @author 芋道源码 18 * @author 芋道源码
21 */ 19 */
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java
1 -package cn.iocoder.yudao.framework.web.core.filter; 1 +package cn.iocoder.yudao.framework.xss.core.filter;
2 2
3 -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; 3 +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
4 4
5 import javax.servlet.http.HttpServletRequest; 5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletRequestWrapper; 6 import javax.servlet.http.HttpServletRequestWrapper;
@@ -13,6 +13,7 @@ import java.util.Map; @@ -13,6 +13,7 @@ import java.util.Map;
13 * @author 芋道源码 13 * @author 芋道源码
14 */ 14 */
15 public class XssRequestWrapper extends HttpServletRequestWrapper { 15 public class XssRequestWrapper extends HttpServletRequestWrapper {
  16 +
16 private final XssCleaner xssCleaner; 17 private final XssCleaner xssCleaner;
17 18
18 public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) { 19 public XssRequestWrapper(HttpServletRequest request, XssCleaner xssCleaner) {
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java renamed to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java
1 -package cn.iocoder.yudao.framework.web.core.json; 1 +package cn.iocoder.yudao.framework.xss.core.json;
2 2
3 -import cn.iocoder.yudao.framework.web.core.clean.XssCleaner; 3 +import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner;
4 import com.fasterxml.jackson.core.JsonParser; 4 import com.fasterxml.jackson.core.JsonParser;
5 import com.fasterxml.jackson.core.JsonToken; 5 import com.fasterxml.jackson.core.JsonToken;
6 import com.fasterxml.jackson.databind.DeserializationContext; 6 import com.fasterxml.jackson.databind.DeserializationContext;
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java 0 → 100644
  1 +/**
  2 + * 针对 XSS 的基础封装
  3 + *
  4 + * XSS 说明:https://tech.meituan.com/2018/09/27/fe-security.html
  5 + */
  6 +package cn.iocoder.yudao.framework.xss;
yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
1 cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration 1 cn.iocoder.yudao.framework.apilog.config.YudaoApiLogAutoConfiguration
2 cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration 2 cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration
3 cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration 3 cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration
4 -cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration  
5 \ No newline at end of file 4 \ No newline at end of file
  5 +cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration
  6 +cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration