getUrlExclusion() {
+ String noneSecurityUrls = ConfigContext.me().getSysConfigValueWithDefault("SYS_XSS_URL_EXCLUSIONS", String.class, "");
+ if (StrUtil.isEmpty(noneSecurityUrls)) {
+ return new ArrayList<>();
+ } else {
+ return StrUtil.split(noneSecurityUrls, ',');
+ }
+ }
+
+}
diff --git a/kernel-d-validator/validator-sdk-xss/README.md b/kernel-d-validator/validator-sdk-xss/README.md
new file mode 100644
index 000000000..2a0518166
--- /dev/null
+++ b/kernel-d-validator/validator-sdk-xss/README.md
@@ -0,0 +1 @@
+XSS过滤器,有效防止XSS攻击
diff --git a/kernel-d-validator/validator-sdk-xss/pom.xml b/kernel-d-validator/validator-sdk-xss/pom.xml
new file mode 100644
index 000000000..458eda7a7
--- /dev/null
+++ b/kernel-d-validator/validator-sdk-xss/pom.xml
@@ -0,0 +1,31 @@
+
+
+ 4.0.0
+
+
+ cn.stylefeng.roses
+ kernel-d-validator
+ 1.0.0
+
+
+ validator-sdk-xss
+
+
+
+
+
+ cn.stylefeng.roses
+ validator-api
+ 1.0.0
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
diff --git a/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssFilter.java b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssFilter.java
new file mode 100644
index 000000000..ccfcf19cb
--- /dev/null
+++ b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssFilter.java
@@ -0,0 +1,51 @@
+package cn.stylefeng.roses.kemel.xss;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.stylefeng.roses.kemel.xss.prop.XssProperties;
+import org.springframework.util.AntPathMatcher;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+
+
+/**
+ * XSS过滤器,使用 XssHttpServletRequestWrapper 将 HttpServletRequest 对象进行包装
+ *
+ * 用于进行param传参方式的参数过滤掉危险标志
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:45
+ */
+public class XssFilter implements Filter {
+
+ public static final String FILTER_NAME = "GUNS_XSS_FILTER";
+
+ private final XssProperties xssProperties;
+
+ public XssFilter(XssProperties xssProperties) {
+ this.xssProperties = xssProperties;
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+ HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ String servletPath = httpServletRequest.getServletPath();
+ String contextPath = httpServletRequest.getContextPath();
+ AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+ // 如果当前servlet path排除在外,则放行
+ if (xssProperties != null &&
+ ObjectUtil.isNotEmpty(xssProperties.getUrlExclusion())) {
+ for (String exclusion : xssProperties.getUrlExclusion()) {
+ if (antPathMatcher.match(contextPath + exclusion, servletPath)) {
+ chain.doFilter(request, response);
+ return;
+ }
+ }
+ }
+
+ // 对原有request对象进行包装
+ chain.doFilter(new XssHttpServletRequestWrapper((HttpServletRequest) request), response);
+ }
+
+}
diff --git a/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssHttpServletRequestWrapper.java b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssHttpServletRequestWrapper.java
new file mode 100644
index 000000000..2eaa34f4a
--- /dev/null
+++ b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssHttpServletRequestWrapper.java
@@ -0,0 +1,73 @@
+package cn.stylefeng.roses.kemel.xss;
+
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HtmlUtil;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+/**
+ * 对原有HttpServletRequest包装,在执行获取参数等操作时候,进行xss过滤
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:50
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+ public XssHttpServletRequestWrapper(HttpServletRequest servletRequest) {
+ super(servletRequest);
+ }
+
+ /**
+ * 获取所有param方式传参的属性的值
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:52
+ */
+ public String[] getParameterValues(String parameter) {
+
+ // 获取所有参数
+ String[] values = super.getParameterValues(parameter);
+ if (ObjectUtil.isEmpty(values)) {
+ return values;
+ }
+
+ // 针对每一个string参数进行过滤
+ String[] encodedValues = new String[values.length];
+ for (int i = 0; i < values.length; i++) {
+ encodedValues[i] = HtmlUtil.filter(values[i]);
+ }
+
+ return encodedValues;
+ }
+
+ /**
+ * 获取单个param方式传参的属性的值
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:52
+ */
+ public String getParameter(String parameter) {
+ String value = super.getParameter(parameter);
+ if (ObjectUtil.isEmpty(value)) {
+ return value;
+ }
+ return HtmlUtil.filter(value);
+ }
+
+ /**
+ * 获取header的值
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:53
+ */
+ public String getHeader(String name) {
+ String value = super.getHeader(name);
+ if (ObjectUtil.isEmpty(value)) {
+ return value;
+ }
+ return HtmlUtil.filter(value);
+ }
+
+}
diff --git a/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssJacksonDeserializer.java b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssJacksonDeserializer.java
new file mode 100644
index 000000000..48d7e248d
--- /dev/null
+++ b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/XssJacksonDeserializer.java
@@ -0,0 +1,47 @@
+package cn.stylefeng.roses.kemel.xss;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.http.HtmlUtil;
+import cn.stylefeng.roses.kemel.xss.prop.XssProperties;
+import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import org.springframework.util.AntPathMatcher;
+
+import java.io.IOException;
+
+/**
+ * 针对于jackson反序列化时,xss危险字符串的过滤
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:56
+ */
+public class XssJacksonDeserializer extends JsonDeserializer {
+
+ private final XssProperties xssProperties;
+
+ public XssJacksonDeserializer(XssProperties xssProperties) {
+ this.xssProperties = xssProperties;
+ }
+
+ @Override
+ public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException {
+ String servletPath = HttpServletUtil.getRequest().getServletPath();
+ String contextPath = HttpServletUtil.getRequest().getContextPath();
+ AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+ // 如果当前servlet path排除在外,则放行
+ if (xssProperties != null &&
+ ObjectUtil.isNotEmpty(xssProperties.getUrlExclusion())) {
+ for (String exclusion : xssProperties.getUrlExclusion()) {
+ if (antPathMatcher.match(contextPath + exclusion, servletPath)) {
+ return jsonParser.getText();
+ }
+ }
+ }
+
+ return HtmlUtil.filter(jsonParser.getText());
+ }
+
+}
diff --git a/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/prop/XssProperties.java b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/prop/XssProperties.java
new file mode 100644
index 000000000..c3a0fb074
--- /dev/null
+++ b/kernel-d-validator/validator-sdk-xss/src/main/java/cn/stylefeng/roses/kemel/xss/prop/XssProperties.java
@@ -0,0 +1,26 @@
+package cn.stylefeng.roses.kemel.xss.prop;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * Xss的相关配置
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 22:46
+ */
+@Data
+public class XssProperties {
+
+ /**
+ * xss过滤的servlet范围,用在设置filter的urlPattern
+ */
+ private String[] urlPatterns;
+
+ /**
+ * 不被xss过滤的url(ANT风格表达式)
+ */
+ private List urlExclusion;
+
+}
diff --git a/kernel-d-validator/validator-spring-boot-starter/pom.xml b/kernel-d-validator/validator-spring-boot-starter/pom.xml
index 42f6bb31e..9415f978c 100644
--- a/kernel-d-validator/validator-spring-boot-starter/pom.xml
+++ b/kernel-d-validator/validator-spring-boot-starter/pom.xml
@@ -38,6 +38,13 @@
1.0.0
+
+
+ cn.stylefeng.roses
+ validator-sdk-xss
+ 1.0.0
+
+
diff --git a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/resolver/MethodArgumentResolver.java b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/MethodArgumentResolverAutoConfiguration.java
similarity index 80%
rename from kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/resolver/MethodArgumentResolver.java
rename to kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/MethodArgumentResolverAutoConfiguration.java
index 36ca3628f..49d32564d 100644
--- a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/resolver/MethodArgumentResolver.java
+++ b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/MethodArgumentResolverAutoConfiguration.java
@@ -1,7 +1,7 @@
-package cn.stylefeng.roses.kernel.validator.starter.resolver;
+package cn.stylefeng.roses.kernel.validator.starter;
-import cn.stylefeng.roses.kernel.validator.starter.web.GunsValidator;
-import cn.stylefeng.roses.kernel.validator.starter.web.ValidatorRequestResponseBodyMethodProcessor;
+import cn.stylefeng.roses.kernel.validator.starter.mvc.GunsValidator;
+import cn.stylefeng.roses.kernel.validator.starter.mvc.GunsValidatorRequestResponseBodyMethodProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
import org.springframework.context.annotation.Bean;
@@ -23,7 +23,7 @@ import java.util.Objects;
*/
@Configuration
@AutoConfigureBefore(ValidationAutoConfiguration.class)
-public class MethodArgumentResolver {
+public class MethodArgumentResolverAutoConfiguration {
@Resource
private RequestMappingHandlerAdapter adapter;
@@ -48,7 +48,7 @@ public class MethodArgumentResolver {
@PostConstruct
public void injectSelfMethodArgumentResolver() {
List argumentResolvers = new ArrayList<>();
- argumentResolvers.add(new ValidatorRequestResponseBodyMethodProcessor(adapter.getMessageConverters()));
+ argumentResolvers.add(new GunsValidatorRequestResponseBodyMethodProcessor(adapter.getMessageConverters()));
argumentResolvers.addAll(Objects.requireNonNull(adapter.getArgumentResolvers()));
adapter.setArgumentResolvers(argumentResolvers);
}
diff --git a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/XssFilterAutoConfiguration.java b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/XssFilterAutoConfiguration.java
new file mode 100644
index 000000000..598525792
--- /dev/null
+++ b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/XssFilterAutoConfiguration.java
@@ -0,0 +1,66 @@
+package cn.stylefeng.roses.kernel.validator.starter;
+
+import cn.stylefeng.roses.kemel.xss.XssFilter;
+import cn.stylefeng.roses.kemel.xss.XssJacksonDeserializer;
+import cn.stylefeng.roses.kemel.xss.prop.XssProperties;
+import cn.stylefeng.roses.kernel.validator.expander.XssConfigExpander;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE;
+
+/**
+ * XSS安全过滤器相关配置
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 23:05
+ */
+@Configuration
+public class XssFilterAutoConfiguration {
+
+ /**
+ * XSS Filter过滤器,用来过滤param之类的传参
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 23:09
+ */
+ @Bean
+ public FilterRegistrationBean xssFilterFilterRegistrationBean() {
+ XssProperties properties = createProperties();
+
+ FilterRegistrationBean xssFilterFilterRegistrationBean = new FilterRegistrationBean<>();
+ xssFilterFilterRegistrationBean.setFilter(new XssFilter(properties));
+ xssFilterFilterRegistrationBean.addUrlPatterns(properties.getUrlPatterns());
+ xssFilterFilterRegistrationBean.setName(XssFilter.FILTER_NAME);
+ xssFilterFilterRegistrationBean.setOrder(HIGHEST_PRECEDENCE);
+ return xssFilterFilterRegistrationBean;
+ }
+
+ /**
+ * XSS的json反序列化器,针对json的传参
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 23:09
+ */
+ @Bean
+ public Jackson2ObjectMapperBuilderCustomizer xssJackson2ObjectMapperBuilderCustomizer() {
+ return jacksonObjectMapperBuilder ->
+ jacksonObjectMapperBuilder.deserializerByType(String.class, new XssJacksonDeserializer(new XssProperties()));
+ }
+
+ /**
+ * 组装xss的配置
+ *
+ * @author fengshuonan
+ * @date 2021/1/13 23:13
+ */
+ private XssProperties createProperties() {
+ XssProperties xssProperties = new XssProperties();
+ xssProperties.setUrlPatterns(XssConfigExpander.getUrlPatterns());
+ xssProperties.setUrlExclusion(XssConfigExpander.getUrlExclusion());
+ return xssProperties;
+ }
+
+}
diff --git a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/web/GunsValidator.java b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/GunsValidator.java
similarity index 95%
rename from kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/web/GunsValidator.java
rename to kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/GunsValidator.java
index 5823aad8c..03181e1ea 100644
--- a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/web/GunsValidator.java
+++ b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/GunsValidator.java
@@ -1,4 +1,4 @@
-package cn.stylefeng.roses.kernel.validator.starter.web;
+package cn.stylefeng.roses.kernel.validator.starter.mvc;
import cn.stylefeng.roses.kernel.validator.context.RequestGroupContext;
import lombok.extern.slf4j.Slf4j;
diff --git a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/web/ValidatorRequestResponseBodyMethodProcessor.java b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/GunsValidatorRequestResponseBodyMethodProcessor.java
similarity index 89%
rename from kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/web/ValidatorRequestResponseBodyMethodProcessor.java
rename to kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/GunsValidatorRequestResponseBodyMethodProcessor.java
index c056ea676..478363b18 100644
--- a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/web/ValidatorRequestResponseBodyMethodProcessor.java
+++ b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/GunsValidatorRequestResponseBodyMethodProcessor.java
@@ -1,4 +1,4 @@
-package cn.stylefeng.roses.kernel.validator.starter.web;
+package cn.stylefeng.roses.kernel.validator.starter.mvc;
import cn.stylefeng.roses.kernel.validator.context.RequestParamContext;
import org.springframework.core.Conventions;
@@ -21,9 +21,9 @@ import java.util.List;
* @author fengshuonan
* @date 2020/8/21 20:51
*/
-public class ValidatorRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {
+public class GunsValidatorRequestResponseBodyMethodProcessor extends RequestResponseBodyMethodProcessor {
- public ValidatorRequestResponseBodyMethodProcessor(List> converters) {
+ public GunsValidatorRequestResponseBodyMethodProcessor(List> converters) {
super(converters);
}
diff --git a/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/package-info.java b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/package-info.java
new file mode 100644
index 000000000..a16a437dc
--- /dev/null
+++ b/kernel-d-validator/validator-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/validator/starter/mvc/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * 这个包内容是对spring mvc原有的一些机制的拓展,为了方便校验器对 RequestGroupContext 之类的上下文添值
+ */
+package cn.stylefeng.roses.kernel.validator.starter.mvc;
diff --git a/kernel-d-validator/validator-spring-boot-starter/src/main/resources/META-INF/spring.factories b/kernel-d-validator/validator-spring-boot-starter/src/main/resources/META-INF/spring.factories
index 0168033ff..0c13f496f 100644
--- a/kernel-d-validator/validator-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/kernel-d-validator/validator-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.stylefeng.roses.kernel.validator.starter.ValidatorAutoConfiguration,\
-cn.stylefeng.roses.kernel.validator.starter.resolver.MethodArgumentResolver
\ No newline at end of file
+cn.stylefeng.roses.kernel.validator.starter.MethodArgumentResolverAutoConfiguration,\
+cn.stylefeng.roses.kernel.validator.starter.XssFilterAutoConfiguration