【SpringBoot XSS存储漏洞 拦截器】Java纯后端对于前台输入值的拦截校验实现 一个类加一个注解结束

先看效果:

1.js注入拦截:
在这里插入图片描述

2.sql注入拦截

在这里插入图片描述

生效只需要两步:

1.创建Filter类,粘贴如下代码:

package cn.你的包命.filter;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.*;
import java.util.regex.Pattern;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;

/**
 * LX:XSS对输入值进行过滤,包括数据库关键词、js注入关键词
 */
@WebFilter(filterName = "xssFilter",urlPatterns = "/*",dispatcherTypes = DispatcherType.REQUEST)
public class CrosXssFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(CrosXssFilter.class);
    private static final String xssMsg = "XssERROR 拦截:发现非法的输入值!";

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if(servletResponse instanceof HttpServletResponse){
            HttpServletResponse httpServletResponse=(HttpServletResponse)servletResponse;
            httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
            httpServletResponse.setHeader("Access-Control-Allow-Methods", "*");
            httpServletResponse.setHeader("Access-Control-Max-Age", "86400");
            httpServletResponse.setHeader("Access-Control-Allow-Headers", "*");
        }

        XssAndSqlHttpServletRequestWrapper xssRequest=new XssAndSqlHttpServletRequestWrapper(request);
        String method = ((HttpServletRequest) request).getMethod();

        String param = "";

        if ("POST".equalsIgnoreCase(method)) {
            param = this.getBodyString(xssRequest.getReader());
            if(StringUtils.hasText(param)){
                if(xssRequest.checkXSSAndSql(param)){
                    response.setCharacterEncoding("UTF-8");
                    response.setStatus(200);
                    response.setContentType("application/json;charset=UTF-8");
                    PrintWriter out = servletResponse.getWriter();
                    Map res = new LinkedHashMap();
                    res.put("status","0");
                    res.put("msg",xssMsg);
                    out.print(JSON.toJSON(res));
                    out.flush();
                    out.close();
                    return;
                }
            }
        }

        if (xssRequest.checkParameter()) {
            response.setCharacterEncoding("UTF-8");
            response.setStatus(200);
            response.setContentType("application/json;charset=UTF-8");
            PrintWriter out = servletResponse.getWriter();
            Map res = new LinkedHashMap();
            res.put("status","0");
            res.put("msg",xssMsg);
            out.print(JSON.toJSON(res));
            out.flush();
            out.close();
            return;
        }
        filterChain.doFilter(xssRequest, servletResponse);
    }


    // 获取request请求body中参数
    public String getBodyString(BufferedReader br) {
        String inputLine;
        String str = "";
        try {
            while ((inputLine = br.readLine()) != null) {
                str += inputLine;
            }
            br.close();
        } catch (IOException e) {
            logger.error("IOException: " ,e);
        }
        return str;

    }

    @Override
    public void destroy() {
    }

    private class XssAndSqlHttpServletRequestWrapper extends HttpServletRequestWrapper {

        private final Logger logger = LoggerFactory.getLogger(XssAndSqlHttpServletRequestWrapper.class);

        //在这里配置要防的词汇
        private String key = "insert|select|delete|drop|update|truncate";
        private Set<String> notAllowedKeyWords = new HashSet<String>(0);

        HttpServletRequest orgRequest = null;
        private Map<String, String[]> parameterMap;
        private final byte[] body; //用于保存读取body中数据

        public XssAndSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException{
            super(request);
            orgRequest = request;
            parameterMap = request.getParameterMap();
            body = StreamUtils.copyToByteArray(request.getInputStream());

            String keyStr[] = key.split("\\|");
            for (String str : keyStr) {
                notAllowedKeyWords.add(str);
            }
        }

        @Override
        public Enumeration<String> getParameterNames() {
            Vector<String> vector = new Vector<String>(parameterMap.keySet());
            return vector.elements();
        }

        /**
         * 参数值进行检查
         */
        @Override
        public String getParameter(String name) {
            String[] results = parameterMap.get(name);
            if (results == null || results.length == 0)
                return null;
            else {
                String value = results[0];
                if (value != null) {
                    value = xssEncode(value);
                }
                return value;
            }
        }

        /**
         * 对于数组型的参数值进行检查
         */
        @Override
        public String[] getParameterValues(String name) {
            String[] results = parameterMap.get(name);
            if (results == null || results.length == 0)
                return null;
            else {
                int length = results.length;
                for (int i = 0; i < length; i++) {
                    results[i] = xssEncode(results[i]);
                }
                return results;
            }
        }

        /**
         * 对参数名进行检查
         */
        @Override
        public String getHeader(String name) {

            String value = super.getHeader(xssEncode(name));
            if (value != null) {
                value = xssEncode(value);
            }
            return value;
        }

        /**
         * LX:在这儿,就可以防住有时候客户输入了单双引号,导致页面的js被截断的问题
         *
         * @param s
         * @return
         */
        private String xssEncode(String s) {
            if (s == null || s.isEmpty()) {
                return s;
            } else {
                s = stripXSSAndSql(s);
            }
            StringBuilder sb = new StringBuilder(s.length() + 16);
            for (int i = 0; i < s.length(); i++) {
                char c = s.charAt(i);
                switch (c) {
                    case '\'':
                        sb.append("'");// 转义单引号
                        break;
                    case '\"':
                        sb.append(""");// 转义双引号
                        break;
                    case '&':
                        sb.append("&");// 转义&
                        break;
                    default:
                        sb.append(c);
                        break;
                }
            }


            return sb.toString();
        }

        public HttpServletRequest getOrgRequest() {
            return orgRequest;
        }

        @SuppressWarnings("unused")
        public HttpServletRequest getOrgRequest(HttpServletRequest req) {
            if (req instanceof XssAndSqlHttpServletRequestWrapper) {
                return ((XssAndSqlHttpServletRequestWrapper) req).getOrgRequest();
            }

            return req;
        }

        /**
         *
         * 防止xss跨脚本攻击(替换,根据实际情况调整)
         */

        public String stripXSSAndSql(String value) {
            if (value != null) {
                /** value = value.replaceAll("", ""); ***/
                Pattern scriptPattern = Pattern.compile(
                        "&lt;[\r\n| | ]*script[\r\n| | ]*&gt;(.*?)<!--[\r\n| | ]*script[\r\n| | ]*-->", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Remove any lonesome  tag
                scriptPattern = Pattern.compile("<!--[\r\n| | ]*script[\r\n| | ]*-->", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Remove any lonesome <script ...> tag
                scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid eval(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid e-xpression(...) expressions
                scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                value = scriptPattern.matcher(value).replaceAll("");
                // Avoid οnlοad= expressions
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                value = scriptPattern.matcher(value).replaceAll("");
            }
            return value;
        }

        public boolean checkXSSAndSql(String value) {
            boolean flag = false;
            if (value != null) {
                // Avoid anything between script tags
                Pattern scriptPattern = Pattern.compile(
                        "<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| | ]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid anything in a
                // src="http://www.yihaomen.com/article/java/..." type of
                // e-xpression
                scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| | ]*[\\\"|\\\'](.*?)[\\\"|\\\']",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Remove any lonesome </script> tag
                scriptPattern = Pattern.compile("<!--[\r\n| | ]*script[\r\n| | ]*-->", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Remove any lonesome <script ...> tag
                scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid eval(...) expressions
                scriptPattern = Pattern.compile("eval\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid e-xpression(...) expressions
                scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid javascript:... expressions
                scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid vbscript:... expressions
                scriptPattern = Pattern.compile("vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }
                // Avoid οnlοad= expressions
                scriptPattern = Pattern.compile("onload(.*?)=",
                        Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
                flag = scriptPattern.matcher(value).find();
                if (flag) {
                    return flag;
                }

                flag=checkSqlKeyWords(value);
            }
            return flag;
        }

        public boolean checkSqlKeyWords(String value){
            String paramValue = value.toLowerCase();//转成小写
            for (String keyword : notAllowedKeyWords) {
                if (paramValue.length() > keyword.length() + 4
                        && (paramValue.contains(" "+keyword)||paramValue.contains(keyword+" ")||paramValue.contains(" "+keyword+" "))) {

                    logger.error(this.getRequestURI()+ "SQL参数中包含敏感词汇(" + keyword
                            + ")");
                    return true;
                }
            }
            return false;
        }

        public final boolean checkParameter() {

            @SuppressWarnings({ "unchecked", "rawtypes" })
            Map<String, String[]> submitParams = new HashMap(parameterMap);

            Set<String> submitNames = submitParams.keySet();
            for (String submitName : submitNames) {
                Object submitValues = submitParams.get(submitName);
                if ((submitValues instanceof String)) {
                    if (checkXSSAndSql((String) submitValues)) {
                        return true;
                    }
                } else if ((submitValues instanceof String[])) {
                    for (String submitValue : (String[])submitValues){
                        if (checkXSSAndSql(submitValue)) {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        @Override
        public BufferedReader getReader() throws IOException {
            return new BufferedReader(new InputStreamReader(getInputStream()));
        }

        @Override
        public ServletInputStream getInputStream() throws IOException {
            final ByteArrayInputStream bais = new ByteArrayInputStream(body);
            return new ServletInputStream() {

                @Override
                public int read() throws IOException {
                    return bais.read();
                }
            };
        }

    }

}

2.springboot启动类上加上扫描注解:

@ServletComponentScan
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 拦截器和过滤器都是Java Web开发中常用的组件,它们的作用是在请求到达目标资源之前或之后对请求进行拦截和处理。 拦截器Spring框架中的概念,通过实现HandlerInterceptor接口来实现。它可以拦截Controller的请求处理过程,包括请求到达Controller之前、请求处理完成之后等多个阶段,并且可以对请求进行一些预处理和后处理,例如:权限验证、日志记录等。拦截器的优点是可以对请求进行更细粒度的控制,更加灵活,但是需要在Spring容器中使用。 过滤器是Servlet规范中的概念,通过实现Filter接口来实现。它可以拦截所有的请求,包括静态资源的请求,过滤器是在请求到达目标资源之前进行拦截处理,可以进行一些预处理,例如:字符编码转换、XSS攻击防范等。过滤器的优点是可以对所有的请求进行统一处理,但是无法对请求的处理过程进行干预。 综上所述,拦截器和过滤器都是Java Web开发中常用的组件,它们都可以对请求进行拦截和处理,但是拦截器更加灵活,可以对请求进行更细粒度的控制;过滤器则可以对所有的请求进行统一处理。 ### 回答2: 拦截器和过滤器是在Java Web开发中常用的两种组件,用于处理请求和响应。 1. 拦截器(Interceptor): 拦截器是基于Java的动态代理机制实现的,主要用于在请求处理的前后执行一些额外的逻辑。它通常被用于AOP(面向切面编程)中,可以实现日志记录、性能监控、权限验证等功能。拦截器可以拦截Controller中的方法,对其中的参数和返回进行处理。拦截器的生命周期由框架控制,通常可以在配置文件中声明。 2. 过滤器(Filter): 过滤器是Java Servlet规范中定义的一种机制,用于在请求到达目标资源之前和离开目标资源之后执行一系列的操作。它可以用于过滤请求参数、处理编码、过滤敏感信息等。过滤器的生命周期也由容器管理,可以在Web.xml文件中配置。 区别: 1. 实现方式:拦截器是基于动态代理实现的,而过滤器是Java Servlet规范中定义的一种组件。 2. 作用对象:拦截器作用于Controller中的方法,而过滤器作用于整个请求(包括请求参数、URL、头部信息等)。 3. 调用顺序:拦截器只关心对Controller方法的拦截,它可以在方法执行前后进行操作。过滤器在请求到达目标资源之前执行,离开目标资源之后执行,也就是在Controller方法执行前后的两个时间点都会执行过滤器。 4. 生命周期:拦截器的生命周期由框架控制,而过滤器的生命周期由容器管理。 综上所述,拦截器和过滤器在实现方式、作用对象、调用顺序和生命周期等方面存在一定的差异。在使用时,我们可以根据具体需求选择合适的组件来完成相应的任务。 ### 回答3: 拦截器和过滤器都是在Java开发中常用的组件,用于对请求进行处理和加工。它们的主要区别在于作用范围、运行顺序和使用方式。 首先,拦截器是在Spring框架中使用的概念,而过滤器是在Java Servlet规范中定义的。所以,拦截器Spring MVC项目中使用得较多,而过滤器则在Java Web项目中常见。 其次,拦截器是基于面向切面编程的思想,它可以拦截并加工控制器层的请求和响应,对其进行处理。而过滤器是对请求进行处理的一种通用机制,它可以对所有的请求进行拦截和处理,比如对请求进行认证、日志记录等操作。 在运行顺序上,拦截器是在控制器(Controller)处理请求之前或之后执行的,可以在处理请求之前进行权限检查、参数校验等操作,也可以在处理请求之后进行日志记录、结果处理等操作。而过滤器则是在请求进入容器之前或之后执行的,它对请求进行拦截和加工,可以对请求参数、请求头等进行修改或加工。 此外,拦截器是通过Spring框架进行管理和配置的,可以使用注解或配置文件来定义拦截器的使用范围和顺序。过滤器则是在web.xml文件中进行配置的,可以配置多个过滤器,并按照配置的顺序进行执行。 综上所述,拦截器和过滤器在作用范围、运行顺序和使用方式上存在一些差异。对于Java领域的专家来说,理解和熟练运用拦截器和过滤器的区别能够帮助我们更好地进行代码编写和项目开发。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值