文章目录
背景
框架中添加xss攻击过滤器类,防止脚本攻击,能够做到引入包即可使用。
参考资料
这里主要参考renren-fast官方提供的开源项目的xss攻击进行改造。
参考io/renren/common/xss包下面类
三方包 hutool-http,参考博客api里面提供了xss所需的标签替换等功能
上代码
过滤器配置
/**
* Filter配置
*
* @author lirui
*/
@Configuration
public class FilterConfig {
/**
* 注册过滤器
*
* @param url 提供可不拦截接口
* 实现配置不过滤部分接口,部分接口需要不做过滤
* @return
*/
@Bean
public FilterRegistrationBean xssFilterRegistration(XssIgnoreFilterUrl url) {
FilterRegistrationBean registration = getFilterRegistrationBean(url);
return registration;
}
private FilterRegistrationBean getFilterRegistrationBean(XssIgnoreFilterUrl url) {
FilterRegistrationBean registration = new FilterRegistrationBean();
//指定发起请求时过滤
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter(Objects.isNull(url) ? null : url.getUrls()));
//默认所有接口
registration.addUrlPatterns("/*");
registration.setName("xssFilter");
//设置最后执行,防止有其他过滤器对值需要修改等操作,保证最后过滤字符即可
registration.setOrder(Integer.MAX_VALUE);
return registration;
}
}
可配置不过滤地址
/**
* xss忽略过滤地址
*
* @author LiRui
* @version 1.0
*/
@Configuration
@ConfigurationProperties(prefix = "xss.ignore")
public class XssIgnoreFilterUrl {
private Set<String> urls;
public Set<String> getUrls() {
return urls;
}
public void setUrls(Set<String> urls) {
this.urls = urls;
}
}
//yml配置
xss:
ignore:
urls:
- /xss/form
主要过滤器代码
/**
* XSS过滤
*
* @author lirui
*/
public class XssFilter implements Filter {
private Set<String> excludedUris;
public XssFilter() {
}
public XssFilter(Set<String> excludedUris) {
this.excludedUris = excludedUris;
}
/**
* 是否排除
*
* @param uri
* @return
*/
private boolean isExcludedUri(String uri) {
if (CollectionUtils.isEmpty(excludedUris)) {
return false;
}
for (String ex : excludedUris) {
if (match(ex, uri)) {
return true;
}
}
return false;
}
/**
* 地址匹配
*
* @param patternPath
* @param requestPath
* @return
*/
public static boolean match(String patternPath, String requestPath) {
if (StringUtils.isEmpty(patternPath) || StringUtils.isEmpty(requestPath)) {
return false;
}
PathMatcher matcher = new AntPathMatcher();
return matcher.match(patternPath, requestPath);
}
@Override
public void init(FilterConfig config) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
//可配置多个字符串过滤
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(
(HttpServletRequest) request, new HTMLFilter());
String url = xssRequest.getServletPath();
if (isExcludedUri(url)) {
chain.doFilter(request, response);
return;
}
chain.doFilter(xssRequest, response);
}
@Override
public void destroy() {
}
}
这里注意match方法,用的Spring包的地址匹配工具,通过匹配地址是否需要过滤
xss具体过滤规则
代码较多我就不贴,最后我会上传到gtee仓库。主要注意,renren-fast中如果存在<或者> 单个的,就会自动在求前面或者最后面进行添加另一符号。在过滤时就会删除前面或者后面内容,具体的可以自己试试renrenfast的代码,内容用<或者>一个符号加内容测试就明白了我的意思。 源代码中我将这段代码注释:
//自动补充<,> 注释允许传递<>符号
// s = regexReplace(P_BODY_TO_END, "<$1>", s);
// s = regexReplace(P_XML_CONTENT, "$1<$2", s);
遇到这种标签,源码中返回的是xxxx,根据业务需求直接返回“”.使用hutool三方包调整代码(仓库中的代码没修改,需要同样需求的自己copy):
return HtmlUtil.cleanHtmlTag(HtmlKit.getTextFromHtml(s));
//getTextFromHtml方法源码
public static String getTextFromHtml(String htmlStr) {
if (htmlStr == null) {
return "";
} else {
htmlStr = delHtmlLabel(htmlStr);
htmlStr = htmlStr.replaceAll(" ", "");
return htmlStr;
}
}
注意扫描该包(或者加starter也行)
@SpringBootApplication(scanBasePackages = {“com.web”})
关于富文本框
开放不做过滤接口配置主要是考虑富文本框的问题,看了很多文章其实主要是处理js脚本,尽量在前端做一次符号转义,然后后端xss攻击过滤器还是需要开启保证安全。
gitee代码仓库
common是过滤器相关源码,web为自己测试的代码