原创

SpringBoot中使用filter的方法和使用filter预防xss攻击

SSM过滤器版本在这里,当然这个你也可以修改为SSM的。
点击进入
在springboot 中,主要是靠FilterRegistrationBean 这个类来提供filter的功能。
自定义Filter需要一下几个步骤:
1.实现Filter【javax.servlet.Filter】接口,实现Filter方法,在doFilter中实现自己的代码
2.创建Filter配置类,添加 @Configuration 注解,将自定义Filter加入过滤器链
以下使用预防Xss攻击作为例子。大致的原理都是一样的。
现在开始代码:
第一步,定义过滤器XssFilter.java

import org.apache.commons.lang3.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 防止XSS攻击的过滤器
 * 
 * @author haohaowang,top
 */
public class XssFilter implements Filter
{
    /**
     * 排除链接(在配置文件中可以自定义,这样可以解耦)
     */
    public List<String> excludes = new ArrayList<>();

    /**
     * xss过滤开关,在配置文件中定义,默认为false
     */
    public boolean enabled = false;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        //在配置过滤器的时候放入参数,在这里可以拿到
        String tempExcludes = filterConfig.getInitParameter("excludes");
        String tempEnabled = filterConfig.getInitParameter("enabled");
        if (StringUtils.isNotEmpty(tempExcludes))
        {
            String[] url = tempExcludes.split(",");
            for (int i = 0; url != null && i < url.length; i++)
            {
                excludes.add(url[i]);
            }
        }
        if (StringUtils.isNotEmpty(tempEnabled))
        {
            enabled = Boolean.valueOf(tempEnabled);
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException
    {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        if (handleExcludeURL(req, resp))
        {
            chain.doFilter(request, response);
            return;
        }
        //自定义的处理方法
        XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
        chain.doFilter(xssRequest, response);
    }

    private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
    {
        if (!enabled)
        {
            return true;
        }
        if (excludes == null || excludes.isEmpty())
        {
            return false;
        }
        String url = request.getServletPath();
        for (String pattern : excludes)
        {
            Pattern p = Pattern.compile("^" + pattern);
            Matcher m = p.matcher(url);
            if (m.find())
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public void destroy()
    {

    }
}

第二步,配置我们写好的过滤器
FilterConfig.java

import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.DispatcherType;
import java.util.Map;

/**
 * Filter配置
 *配置防止xss攻击的拦截器
 */
@Configuration
public class FilterConfig
{
    //配置文件注入配置项,配置是否开启
    @Value("${xss.enabled}")
    private String enabled;
    //配置排出链接,通常排除静态文件
    @Value("${xss.excludes}")
    private String excludes;
    //配置过滤规则,通常是所有的链接都过滤掉
    @Value("${xss.urlPatterns}")
    private String urlPatterns;

    @SuppressWarnings({ "rawtypes", "unchecked" })
    @Bean
    public FilterRegistrationBean xssFilterRegistration()
    {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        //将自定义的Filter加入过滤器链
        registration.setFilter(new XssFilter());
        //(StringUtils.split(urlPatterns, ",")这个方法可以将String切分成数组
        registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
        registration.setName("xssFilter");
        //order 值越大优先级越低
        registration.setOrder(Integer.MAX_VALUE);
        Map<String, String> initParameters = Maps.newHashMap();

        initParameters.put("excludes", excludes);
        initParameters.put("enabled", enabled);
    /**
     * Set init-parameters for this registration. Calling this method will replace any
     * existing init-parameters. 设置此注册的init参数。调用此方法将替换一些默认参数。
     * @param initParameters the init parameters
     * @see #getInitParameters
     * @see #addInitParameter
     */
        //这里传递参数到init方法,在上面的代码中可以拿到,我们使用这些参数进行初始化过滤器
        registration.setInitParameters(initParameters);
        return registration;
    }

}

Xss攻击的处理类
XssHttpServletRequestWrapper.java

import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

/**
 * XSS过滤处理
 * 
 */
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
{
    /**
     * @param request
     */
    public XssHttpServletRequestWrapper(HttpServletRequest request)
    {
        super(request);
    }

    @Override
    public String[] getParameterValues(String name)
    {
        String[] values = super.getParameterValues(name);
        if (values != null)
        {
            int length = values.length;
            String[] escapseValues = new String[length];
            for (int i = 0; i < length; i++)
            {
                // 防xss攻击和过滤前后空格
                escapseValues[i] = Jsoup.clean(values[i], Whitelist.relaxed()).trim();
            }
            return escapseValues;
        }
        return super.getParameterValues(name);
    }
}

配置文件中

# 防止XSS攻击
xss:
  # 过滤开关
  enabled: true
  # 排除链接(多个用逗号分隔)
  excludes: /static/*,/login
  # 过滤所有的链接,当然是排除上面配置的
  urlPatterns: /*

效果:
我们在系统的input框中输入

haohaowang"/><script>alert("欢迎来到好好网")</script>

file
点击保存
file
然后就弹出了,这是我们不想要的效果。
我们打开Xss过滤
点击保存后代码变成这样
file
浏览器就不会执行这样的代码。

正文到此结束(点击广告是对作者最大的支持)