Commit 5c0a1a91 authored by zengtianlai3's avatar zengtianlai3

撤销

parent aabdccef
package iot.sixiang.license.xss; //package iot.sixiang.license.xss;
//
/** ///**
* Title: AntiSamyConfig // * Title: AntiSamyConfig
* Description: TODO // * Description: TODO
* // *
* @author tianlai3 // * @author tianlai3
* @date 2022-07-17 01:18:02 // * @date 2022-07-17 01:18:02
*/ // */
import com.fasterxml.jackson.databind.ObjectMapper; //import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule; //import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.boot.web.servlet.FilterRegistrationBean; //import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean; //import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; //import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; //import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
//
import javax.servlet.Filter; //import javax.servlet.Filter;
//
//
@Configuration //@Configuration
public class AntiSamyConfig { //public class AntiSamyConfig {
//
/** // /**
* 配置XSS过滤器 // * 配置XSS过滤器
* // *
* @return FilterRegistrationBean // * @return FilterRegistrationBean
*/ // */
@Bean // @Bean
public FilterRegistrationBean<Filter> filterRegistrationBean() { // public FilterRegistrationBean<Filter> filterRegistrationBean() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new XssFilter2()); // FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new XssFilter2());
filterRegistrationBean.addUrlPatterns("/iot_license/*"); // filterRegistrationBean.addUrlPatterns("/iot_license/*");
filterRegistrationBean.setOrder(1); // filterRegistrationBean.setOrder(1);
return filterRegistrationBean; // return filterRegistrationBean;
} // }
//
/** // /**
* 用于过滤Json类型数据的解析器 // * 用于过滤Json类型数据的解析器
* // *
* @param builder Jackson2ObjectMapperBuilder // * @param builder Jackson2ObjectMapperBuilder
* @return ObjectMapper // * @return ObjectMapper
*/ // */
@Bean // @Bean
public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) { // public ObjectMapper xssObjectMapper(Jackson2ObjectMapperBuilder builder) {
// 创建解析器 // // 创建解析器
ObjectMapper objectMapper = builder.createXmlMapper(false).build(); // ObjectMapper objectMapper = builder.createXmlMapper(false).build();
// 注册解析器 // // 注册解析器
SimpleModule simpleModule = new SimpleModule("XssStringJsonSerializer"); // SimpleModule simpleModule = new SimpleModule("XssStringJsonSerializer");
simpleModule.addSerializer(new XssRequestWrapper2.XssStringJsonSerializer()); // simpleModule.addSerializer(new XssRequestWrapper2.XssStringJsonSerializer());
objectMapper.registerModule(simpleModule); // objectMapper.registerModule(simpleModule);
return objectMapper; // return objectMapper;
} // }
} //}
\ No newline at end of file \ No newline at end of file
...@@ -16,8 +16,8 @@ import java.io.IOException; ...@@ -16,8 +16,8 @@ import java.io.IOException;
* @Date 2022/6/29 11:11 * @Date 2022/6/29 11:11
* @Description * @Description
*/ */
//@WebFilter(filterName = "xssFilter", urlPatterns = "/iot_license/*", asyncSupported = true) @WebFilter(filterName = "xssFilter", urlPatterns = "/iot_license/*", asyncSupported = true)
//@Component @Component
public class XssFilter implements Filter { public class XssFilter implements Filter {
/** /**
......
package iot.sixiang.license.xss; //package iot.sixiang.license.xss;
//
import javax.servlet.*; //import javax.servlet.*;
import javax.servlet.http.HttpServletRequest; //import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; //import javax.servlet.http.HttpServletResponse;
import java.io.IOException; //import java.io.IOException;
//
//@WebFilter(filterName = "xssFilter", urlPatterns = "/iot_license/*", asyncSupported = true) //
//@Component //public class XssFilter2 implements Filter {
public class XssFilter2 implements Filter { //
// private FilterConfig filterConfig;
private FilterConfig filterConfig; //
// @Override
@Override // public void init(FilterConfig filterConfig) throws ServletException {
public void init(FilterConfig filterConfig) throws ServletException { // this.filterConfig = filterConfig;
this.filterConfig = filterConfig; // }
} //
// @Override
@Override // public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) // throws IOException, ServletException {
throws IOException, ServletException { // // 拦截请求,处理XSS过滤
// 拦截请求,处理XSS过滤 // HttpServletRequest req = (HttpServletRequest) request;
HttpServletRequest req = (HttpServletRequest) request; // HttpServletResponse resp = (HttpServletResponse) response;
HttpServletResponse resp = (HttpServletResponse) response; // XssRequestWrapper2 xssRequest = new XssRequestWrapper2(req);
XssRequestWrapper2 xssRequest = new XssRequestWrapper2(req); //
// chain.doFilter(xssRequest, resp);
chain.doFilter(xssRequest, resp); // }
} //
// @Override
@Override // public void destroy() {
public void destroy() { // this.filterConfig = null;
this.filterConfig = null; // }
} //}
} \ No newline at end of file
\ No newline at end of file
package iot.sixiang.license.xss; //package iot.sixiang.license.xss;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
import org.owasp.validator.html.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
/**
* Title: XssRequestWrapper2
* Description: TODO
*
* @author tianlai3
* @date 2022-07-16 22:48:55
*/
@Slf4j
public class XssRequestWrapper2 extends HttpServletRequestWrapper {
private static Policy policy = null;
static {
try {
// 获取策略文件路径,策略文件需要放到项目的classpath下
String antiSamyPath = Objects
.requireNonNull(XssRequestWrapper2.class.getClassLoader().getResource("antisamy-ebay.xml")).getFile();
log.info(antiSamyPath);
// 获取的文件路径中有空格时,空格会被替换为%20,在new一个File对象时会出现找不到路径的错误
// 对路径进行解码以解决该问题
antiSamyPath = URLDecoder.decode(antiSamyPath, "utf-8");
log.info(antiSamyPath);
// 指定策略文件
policy = Policy.getInstance(antiSamyPath);
} catch (UnsupportedEncodingException | PolicyException e) {
log.warn(e.getMessage());
}
}
public XssRequestWrapper2(HttpServletRequest request) {
super(request);
}
/**
* 过滤请求头
*
* @param name 参数名
* @return 参数值
*/
@Override
public String getHeader(String name) {
String header = super.getHeader(name);
// 如果Header为空,则直接返回,否则进行清洗
return StringUtils.isBlank(header) ? header : xssClean(header);
}
/**
* 过滤请求参数
*
* @param name 参数名
* @return 参数值
*/
@Override
public String getParameter(String name) {
String parameter = super.getParameter(name);
// 如果Parameter为空,则直接返回,否则进行清洗
return StringUtils.isBlank(parameter) ? parameter : xssClean(parameter);
}
/**
* 过滤请求参数(一个参数可以有多个值)
*
* @param name 参数名
* @return 参数值数组
*/
@Override
public String[] getParameterValues(String name) {
String[] parameterValues = super.getParameterValues(name);
if (parameterValues != null) {
int length = parameterValues.length;
String[] newParameterValues = new String[length];
for (int i = 0; i < length; i++) {
log.info("AntiSamy清理之前的参数值:" + parameterValues[i]);
// 清洗参数
newParameterValues[i] = xssClean(parameterValues[i]);
log.info("AntiSamy清理之后的参数值:" + newParameterValues[i]);
}
return newParameterValues;
}else{
return null;
}
}
// @Override
// public String[] getParameterValues(String parameter) {
// //
// String[] values = super.getParameterValues(parameter); //import com.fasterxml.jackson.core.JsonGenerator;
//import com.fasterxml.jackson.databind.JsonSerializer;
//import com.fasterxml.jackson.databind.SerializerProvider;
//import lombok.extern.slf4j.Slf4j;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.commons.text.StringEscapeUtils;
//import org.owasp.validator.html.*;
// //
// if (values == null) { //import javax.servlet.http.HttpServletRequest;
//import javax.servlet.http.HttpServletRequestWrapper;
//import java.io.IOException;
//import java.io.UnsupportedEncodingException;
//import java.net.URLDecoder;
//import java.util.Iterator;
//import java.util.Map;
//import java.util.Objects;
// //
// return null; ///**
// * Title: XssRequestWrapper2
// * Description: TODO
// *
// * @author tianlai3
// * @date 2022-07-16 22:48:55
// */
//@Slf4j
//public class XssRequestWrapper2 extends HttpServletRequestWrapper {
// private static Policy policy = null;
// //
// static {
// try {
// // 获取策略文件路径,策略文件需要放到项目的classpath下
// String antiSamyPath = Objects
// .requireNonNull(XssRequestWrapper2.class.getClassLoader().getResource("antisamy-ebay.xml")).getFile();
// log.info(antiSamyPath);
// // 获取的文件路径中有空格时,空格会被替换为%20,在new一个File对象时会出现找不到路径的错误
// // 对路径进行解码以解决该问题
// antiSamyPath = URLDecoder.decode(antiSamyPath, "utf-8");
// log.info(antiSamyPath);
// // 指定策略文件
// policy = Policy.getInstance(antiSamyPath);
// } catch (UnsupportedEncodingException | PolicyException e) {
// log.warn(e.getMessage());
// } // }
// }
// //
// int count = values.length; // public XssRequestWrapper2(HttpServletRequest request) {
// super(request);
// }
// //
// String[] encodedValues = new String[count]; // /**
// * 过滤请求头
// *
// * @param name 参数名
// * @return 参数值
// */
// @Override
// public String getHeader(String name) {
// String header = super.getHeader(name);
// // 如果Header为空,则直接返回,否则进行清洗
// return StringUtils.isBlank(header) ? header : xssClean(header);
// }
// //
// for (int i = 0; i < count; i++) { // /**
//// cleanSQLInject(values[i]); // * 过滤请求参数
// encodedValues[i] = xssClean(values[i]); // *
// * @param name 参数名
// * @return 参数值
// */
// @Override
// public String getParameter(String name) {
// String parameter = super.getParameter(name);
// // 如果Parameter为空,则直接返回,否则进行清洗
// return StringUtils.isBlank(parameter) ? parameter : xssClean(parameter);
// }
// //
// /**
// * 过滤请求参数(一个参数可以有多个值)
// *
// * @param name 参数名
// * @return 参数值数组
// */
// @Override
// public String[] getParameterValues(String name) {
// String[] parameterValues = super.getParameterValues(name);
// if (parameterValues != null) {
// int length = parameterValues.length;
// String[] newParameterValues = new String[length];
// for (int i = 0; i < length; i++) {
// log.info("AntiSamy清理之前的参数值:" + parameterValues[i]);
// // 清洗参数
// newParameterValues[i] = xssClean(parameterValues[i]);
// log.info("AntiSamy清理之后的参数值:" + newParameterValues[i]);
// }
// return newParameterValues;
// }else{
// return null;
// } // }
// }
// //
// return encodedValues; //// @Override
//// public String[] getParameterValues(String parameter) {
////
//// String[] values = super.getParameterValues(parameter);
////
//// if (values == null) {
////
//// return null;
////
//// }
////
//// int count = values.length;
////
//// String[] encodedValues = new String[count];
////
//// for (int i = 0; i < count; i++) {
////// cleanSQLInject(values[i]);
//// encodedValues[i] = xssClean(values[i]);
////
//// }
////
//// return encodedValues;
////
//// }
//// @Override
//// public Map<String, String[]> getParameterMap() {
//// Map<String, String[]> requestMap = super.getParameterMap();
////
////
//// requestMap.forEach((key, value) -> {
//// for (int i = 0; i < value.length; i++) {
//// log.info(value[i]);
//// value[i] = xssClean(value[i]);
//// log.info(value[i]);
//// }
//// });
//// return requestMap;
//// }
// //
// /**
// * 使用AntiSamy清洗数据
// *
// * @param value 需要清洗的数据
// * @return 清洗后的数据
// */
// private String xssClean(String value) {
// try {
// AntiSamy antiSamy = new AntiSamy();
// // 使用AntiSamy清洗数据
// final CleanResults cleanResults = antiSamy.scan(value, policy);
// // 获得安全的HTML输出
// value = cleanResults.getCleanHTML();
// // 对转义的HTML特殊字符(<、>、"等)进行反转义,因为AntiSamy调用scan方法时会将特殊字符转义
// return StringEscapeUtils.unescapeHtml4(value);
// } catch (ScanException | PolicyException e) {
// log.warn(e.getMessage());
// }
// return value;
// } // }
// @Override
// public Map<String, String[]> getParameterMap() {
// Map<String, String[]> requestMap = super.getParameterMap();
// //
// /**
// * 通过修改Json序列化的方式来完成Json格式的XSS过滤
// */
// public static class XssStringJsonSerializer extends JsonSerializer<String> {
//
// @Override
// public Class<String> handledType() {
// return String.class;
// }
// //
// requestMap.forEach((key, value) -> { // @Override
// for (int i = 0; i < value.length; i++) { // public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
// log.info(value[i]); // if (!StringUtils.isBlank(value)) {
// value[i] = xssClean(value[i]); // try {
// log.info(value[i]); // AntiSamy antiSamy = new AntiSamy();
// final CleanResults cleanResults = antiSamy.scan(value, XssRequestWrapper2.policy);
// gen.writeString(StringEscapeUtils.unescapeHtml4(cleanResults.getCleanHTML()));
// } catch (ScanException | PolicyException e) {
// log.warn(e.getMessage());
// }
// } // }
// }); // }
// return requestMap;
// } // }
//}
/** \ No newline at end of file
* 使用AntiSamy清洗数据
*
* @param value 需要清洗的数据
* @return 清洗后的数据
*/
private String xssClean(String value) {
try {
AntiSamy antiSamy = new AntiSamy();
// 使用AntiSamy清洗数据
final CleanResults cleanResults = antiSamy.scan(value, policy);
// 获得安全的HTML输出
value = cleanResults.getCleanHTML();
// 对转义的HTML特殊字符(<、>、"等)进行反转义,因为AntiSamy调用scan方法时会将特殊字符转义
return StringEscapeUtils.unescapeHtml4(value);
} catch (ScanException | PolicyException e) {
log.warn(e.getMessage());
}
return value;
}
/**
* 通过修改Json序列化的方式来完成Json格式的XSS过滤
*/
public static class XssStringJsonSerializer extends JsonSerializer<String> {
@Override
public Class<String> handledType() {
return String.class;
}
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (!StringUtils.isBlank(value)) {
try {
AntiSamy antiSamy = new AntiSamy();
final CleanResults cleanResults = antiSamy.scan(value, XssRequestWrapper2.policy);
gen.writeString(StringEscapeUtils.unescapeHtml4(cleanResults.getCleanHTML()));
} catch (ScanException | PolicyException e) {
log.warn(e.getMessage());
}
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="anti-samy-rules">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="directives" type="Directives" maxOccurs="1" minOccurs="1"/>
<xsd:element name="common-regexps" type="CommonRegexps" maxOccurs="1" minOccurs="1"/>
<xsd:element name="common-attributes" type="AttributeList" maxOccurs="1" minOccurs="1"/>
<xsd:element name="global-tag-attributes" type="AttributeList" maxOccurs="1" minOccurs="1"/>
<xsd:element name="tags-to-encode" type="TagsToEncodeList" minOccurs="0" maxOccurs="1"/>
<xsd:element name="tag-rules" type="TagRules" minOccurs="1" maxOccurs="1"/>
<xsd:element name="css-rules" type="CSSRules" minOccurs="1" maxOccurs="1"/>
<xsd:element name="allowed-empty-tags" type="AllowedEmptyTags" minOccurs="0" maxOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:complexType name="Directives">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="directive" type="Directive" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Directive">
<xsd:attribute name="name" use="required"/>
<xsd:attribute name="value" use="required"/>
</xsd:complexType>
<xsd:complexType name="CommonRegexps">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="regexp" type="RegExp" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="AttributeList">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="attribute" type="Attribute" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TagsToEncodeList">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="tag" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="TagRules">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="tag" type="Tag" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Tag">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="attribute" type="Attribute" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required"/>
<xsd:attribute name="action" use="required"/>
</xsd:complexType>
<xsd:complexType name="AllowedEmptyTags">
<xsd:sequence>
<xsd:element name="literal-list" type="LiteralList" minOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Attribute">
<xsd:sequence>
<xsd:element name="regexp-list" type="RegexpList" minOccurs="0"/>
<xsd:element name="literal-list" type="LiteralList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" use="required"/>
<xsd:attribute name="description"/>
<xsd:attribute name="onInvalid"/>
</xsd:complexType>
<xsd:complexType name="RegexpList">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="regexp" type="RegExp" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="RegExp">
<xsd:attribute name="name" type="xsd:string"/>
<xsd:attribute name="value" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="LiteralList">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="literal" type="Literal" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Literal">
<xsd:attribute name="value" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="CSSRules">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="property" type="Property" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Property">
<xsd:sequence>
<xsd:element name="category-list" type="CategoryList" minOccurs="0"/>
<xsd:element name="literal-list" type="LiteralList" minOccurs="0"/>
<xsd:element name="regexp-list" type="RegexpList" minOccurs="0"/>
<xsd:element name="shorthand-list" type="ShorthandList" minOccurs="0"/>
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="default" type="xsd:string"/>
<xsd:attribute name="description" type="xsd:string"/>
</xsd:complexType>
<xsd:complexType name="ShorthandList">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="shorthand" type="Shorthand" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Shorthand">
<xsd:attribute name="name" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="CategoryList">
<xsd:sequence maxOccurs="unbounded">
<xsd:element name="category" type="Category" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Category">
<xsd:attribute name="value" type="xsd:string" use="required"/>
</xsd:complexType>
<xsd:complexType name="Entity">
<xsd:attribute name="name" type="xsd:string" use="required"/>
<xsd:attribute name="cdata" type="xsd:string" use="required"/>
</xsd:complexType>
</xsd:schema>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment