import com.green.admin.common.utils.core.StringUtils;
import com.green.admin.common.configures.SystemConfig;
import com.green.admin.core.wrappers.XssHttpServletRequestWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Objects;
/**
* 防止XSS攻击的过滤器
*/
@Order(FilterRegistrationBean.HIGHEST_PRECEDENCE)
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
@WebFilter(filterName = "xssFilter", urlPatterns = "/*")
public class XssFilter implements Filter {
private final SystemConfig systemConfig;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
if (handleExcludeUrl(req)) {
chain.doFilter(request, response);
return;
}
if (systemConfig.getXssEnabled()) {
if (handleIncludeUrl(req)) {
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
return;
}
}
chain.doFilter(request, response);
}
/**
* 排除链接操作
*/
private boolean handleExcludeUrl(HttpServletRequest request) {
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (Objects.isNull(method) || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) {
return true;
}
return StringUtils.matches(url, systemConfig.getXssUrlExcludes());
}
/**
* 匹配链接操作
*/
private boolean handleIncludeUrl(HttpServletRequest request) {
String url = request.getServletPath();
return StringUtils.matches(url, systemConfig.getXssUrlPatterns());
}
}
import com.green.admin.common.utils.core.StringUtils;
import com.green.admin.common.utils.html.HtmlUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
/**
* @param request 请求
*/
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getQueryString() {
return HtmlUtils.clean(super.getQueryString());
}
@Override
public String getParameter(String name) {
return HtmlUtils.clean(super.getParameter(name));
}
@Override
public String[] getParameterValues(String name) {
String[] values = super.getParameterValues(name);
if (Objects.nonNull(values)) {
int length = values.length;
String[] escapeValues = new String[length];
for (int i = 0; i < length; i++) {
// 防xss攻击和过滤前后空格
escapeValues[i] = HtmlUtils.clean(values[i]).trim();
}
return escapeValues;
}
return super.getParameterValues(name);
}
@Override
public ServletInputStream getInputStream() throws IOException {
// 非json类型,直接返回
if (!isJsonRequest()) {
return super.getInputStream();
}
// 为空,直接返回
String json = IOUtils.toString(super.getInputStream(), StandardCharsets.UTF_8);
if (StringUtils.isEmpty(json)) {
return super.getInputStream();
}
// xss过滤
json = HtmlUtils.clean(json).trim();
byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
return new ServletInputStream() {
@Override
public boolean isFinished() {
return true;
}
@Override
public boolean isReady() {
return true;
}
@Override
public int available() {
return jsonBytes.length;
}
@Override
public void setReadListener(ReadListener readListener) {
}
@Override
public int read() {
return bis.read();
}
};
}
/**
* 是否是Json请求
*/
public boolean isJsonRequest() {
String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
}
}
@Getter
@Setter
@Component
@SuppressWarnings("all")
@ConfigurationProperties(prefix = "system")
@PropertySource(value = {"classpath:/config/system-config-${spring.profiles.active}.properties",
"file:./config/config/system-config-${spring.profiles.active}.properties"}, ignoreResourceNotFound = true)
public class SystemConfig {
/**
* 防止XSS攻击过滤开关
*/
private Boolean xssEnabled;
/**
* XSS排除链接(多个用逗号分隔)
*/
private List<String> xssUrlExcludes;
/**
* XSS匹配链接
*/
private List<String> xssUrlPatterns;
}system-config-dev.properties
#防止XSS攻击过滤开关
system.xss_enabled=true
#排除链接(多个用逗号分隔)
system.xss_url_excludes=/system/notice
#匹配链接(多个用逗号分隔)
system.xss_url_patterns=/user/*版权声明:本文为luojiawen208原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。