前几天有个客户在系统上写了一段html语句,打开页面就显示一张炒鸡大的图片,影响美观。后来仔细想想,幸亏注入的仅仅是html语句,知道严重性后,马上开始一番系统安全配置。
一. 定义过滤器
package com.cn.unit.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
public class SafeFilter implements Filter{
// 配置信息对象
public FilterConfig filterConfig;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
filterConfig = config;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String enctype = httpRequest.getContentType();
if(StringUtils.isNotBlank(enctype) && enctype.contains("multipart/form-data")){
// 上传文件
CommonsMultipartResolver commonsMultipartResolver = new CommonsMultipartResolver(
httpRequest.getSession().getServletContext());
MultipartHttpServletRequest multipartRequest = commonsMultipartResolver.resolveMultipart(httpRequest);
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper(multipartRequest);
chain.doFilter(xssRequest, response);
}else{
// 普通表单和Ajax
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
}
@Override
public void destroy() {
this.filterConfig = null;
}
}
二. 过滤包装器,实现参数值过滤
package com.cn.unit.filter;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
public class SafeHttpServletRequestWrapper extends HttpServletRequestWrapper{
public SafeHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String getParameter(String name) {
String value = super.getParameter(name);
if (value != null) {
value = xssEncode(value);
}
return value;
}
@Override
public String[] getParameterValues(String name) {
String[] value = super.getParameterValues(name);
if(value != null){
for (int i = 0; i < value.length; i++) {
value[i] = xssEncode(value[i]);
}
}
return value;
}
@Override
public Map getParameterMap() {
return super.getParameterMap();
}
@Override
public String getHeader(String name) {
return super.getHeader(name);
}
private static String xssEncode(String value) {
if (value == null || value.isEmpty()) {
return value;
}
// 防SQL注入转义
value = StringEscapeUtils.escapeSql(value);
// HTML防注入,个人建议使用第三种
// 1.防HTML注入转义(HtmlUtils工具类,汉字不转义,双引号转义,存在JSON封装需要反转义)
value = HtmlUtils.htmlEscape(value);
return value;
}
}
三. 配置web.xml添加过滤器XssSqlFilter com.cn.unit.filter.SafeFilter XssSqlFilter /*
配置各节点简单介绍:
| 节点名 | 介绍 |
|---|---|
| 指定一个过滤器 | |
| 用于为过滤器指定一个名字,该元素的内容不能为空 | |
| 指定过滤器的完整的限定类名 | |
| 为过滤器指定初始化参数。在过滤器中,可以使用FilterConfig接口对象来访问初始化参数 | |
| 设置一个Filter所负责拦截的资源。可通过Servlet名称或资源访问的请求路径指定 | |
| 子元素用于设置filter的注册名称。该值必须是在 |
|
| 设置 filter 所拦截的请求路径(过滤器关联的URL样式) | |
| 指定过滤器所拦截的Servlet名称 | |
| 指定过滤器所拦截的资源被 Servlet 容器调用的方式,默认REQUEST |
在实际开发的过程中,js、css等静态资源也进行过滤,消耗服务器性能,因此把一些不必要过滤的直接跳过过滤器,实现如下:
4.1 在web.xml配置文件中添加参数,保存静态资源所在的路径
excludeFilter /document/;/ligentres/
如图:
4.2 过滤器初始化方法,读取静态资源所在的路径
public FilterConfig filterConfig;
public String[] excludeFilterArray;
@Override
public void init(FilterConfig config) throws ServletException {
filterConfig = config;
// 读取web配置文件中的静态资源所在路径
String excludeFilter = filterConfig.getInitParameter("excludeFilter");
excludeFilterArray = excludeFilter.split(";");
}
4.3 过滤器拦截请求,若是静态资源所在的路径直接跳过过滤器
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String uri = httpRequest.getRequestURI();
// 静态资源直接跳过,不进行过滤
if(uri==null||this.isContains(uri, excludeFilterArray)) {
chain.doFilter(request, response);
return;
}
......
}
// 判断数组是否包含某一元素
public boolean isContains(String uri, String[] regx) {
boolean result = false;
for (int i = 0; i < regx.length; i++) {
if (uri.indexOf(regx[i]) != -1) {
return true;
}
}
return result;
}
五. 大功告成借鉴前人的经验,一开始测试的时候发现,普通的表单提交和ajax提交可以过滤其参数,但上传文件时就无法进入过滤了。
后来经过研究,用于处理文件上传的 MultipartResolver ,当收到请求时,DispatcherServlet 的 checkMultipart() 方法会调用 MultipartResolver 的 isMultipart() 方法判断请求中是否包含文件。如果请求数据中包含文件,则调用 MultipartResolver 的 resolveMultipart() 方法对请求的数据进行解析,然后将文件数据解析成 MultipartFile 并封装在 MultipartHttpServletRequest 对象中,最后传递给 Controller。因此我们只需要在定义过滤器时,先获取请求头判断是否为文件上传,若是再对数据进行解析便可。
到此这篇关于Java使用过滤器防止SQL注入XSS脚本注入的实现的文章就介绍到这了,更多相关Java 过滤器防止SQL注入 内容请搜索考高分网以前的文章或继续浏览下面的相关文章希望大家以后多多支持考高分网!



