diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java index 95955d5ee..b20565eca 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java +++ b/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(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 FilterRegistrationBean createFilterBean(T filter, Integer order) { + public static FilterRegistrationBean createFilterBean(T filter, Integer order) { FilterRegistrationBean bean = new FilterRegistrationBean<>(filter); bean.setOrder(order); return bean; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java similarity index 92% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/XssProperties.java index e4d123089..c914b0465 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/XssProperties.java +++ b/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; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java new file mode 100644 index 000000000..d5d892c07 --- /dev/null +++ b/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(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) { + return createFilterBean(new XssFilter(properties, pathMatcher, xssCleaner), WebFilterOrderEnum.XSS_FILTER); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java similarity index 84% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/JsoupXssCleaner.java index 559267c3f..4cbc907b9 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/JsoupXssCleaner.java +++ b/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; } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java similarity index 83% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/clean/XssCleaner.java index 433f7e775..529bc64a2 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/clean/XssCleaner.java +++ b/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); + } diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java similarity index 80% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssFilter.java index 2da18768d..5f2ce6e3d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssFilter.java +++ b/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 过滤器 - *

- * 对 Xss 不了解的胖友,可以看看 http://www.iocoder.cn/Fight/The-new-girl-asked-me-why-AJAX-requests-are-not-secure-I-did-not-answer/ * * @author 芋道源码 */ diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java similarity index 95% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/filter/XssRequestWrapper.java index 7beed46cc..35819f443 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/XssRequestWrapper.java +++ b/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) { diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java similarity index 94% rename from yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/core/json/XssStringJsonDeserializer.java index 7e1f631c7..2b1725d96 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/json/XssStringJsonDeserializer.java +++ b/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; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/package-info.java new file mode 100644 index 000000000..c6e46f070 --- /dev/null +++ b/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; diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 2a422bfa2..818e33aa3 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/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 \ No newline at end of file +cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration +cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration