springboot在Filter中过滤request的请求参数

工作 / 2023-11-14

springboot在Filter中过滤request的请求参数

什么是sql注入

是一种代码注入技术,用于攻击数据驱动的应用,恶意的SQL语句被插入到执行的实体字段中(例如,为了转储数据库内容给攻击者)

通过Filter来过滤请求的参数

Filter:

import MyRequestWrapper;
import lombok.RequiredArgsConstructor;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


/**
 * &#064;description: filter过滤器,默认拦截所有请求<BR/>
 * &#064;author: monster <BR/>
 * &#064;date: 2023/11/14  <BR/>
 */
@RequiredArgsConstructor
public class SqlFilter extends OncePerRequestFilter {


    @Override
    protected void doFilterInternal(HttpServletRequest request
            , HttpServletResponse response
            , FilterChain filterChain) throws ServletException, IOException {
        // 请求重写
        MyRequestWrapper requestWrapper = new MyRequestWrapper(request);
        filterChain.doFilter(requestWrapper, response);
    }
}

注入类:

import SqlFilter;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.context.annotation.Bean;


@AutoConfiguration
public class TemeiSqlConfiguration {

    @Bean
    public SqlFilter sqlFrameworkService() {
        return new SqlFilter();
    }


}

添加 resources/META-INF/spring

org.springframework.boot.autoconfigure.AutoConfiguration.imports

TemeiSqlConfiguration

过滤实现类

import org.apache.catalina.util.ParameterMap;
import org.apache.commons.codec.Charsets;

import javax.servlet.ReadListener;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.Part;
import java.io.*;
import java.util.*;

/**
 * <p> @Title MyRequestWrapper
 * <p> @Description 过滤请求中的关键词
 *
 * @author monster
 * @date 2023/11/14
 */
public class MyRequestWrapper extends HttpServletRequestWrapper {
    private String body;


    public MyRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);

        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        try {
            InputStream inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                char[] charBuffer = new char[128];
                int bytesRead = -1;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            } else {
                stringBuilder.append("");
            }
        } catch (IOException ex) {
            throw ex;
        } finally {
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException ex) {
                    throw ex;
                }
            }
        }
        //校验请求体并替换
        body = checkSqlInject(stringBuilder.toString());

    }


    public static String dostring(String str) {
        str = str.replaceAll(";", "");
        str = str.replaceAll("&", "&amp;");
        str = str.replaceAll("<", "&lt;");
        str = str.replaceAll(">", "&gt;");
        str = str.replaceAll("'", "*");
        str = str.replaceAll("--", "*");
//        str=str.replaceAll("/","*");
        str = str.replaceAll("%", "*");
        str = str.replaceAll("select", "***");
        str = str.replaceAll("update", "***");
        str = str.replaceAll("delete", "***");
        str = str.replaceAll("insert", "***");
        str = str.replaceAll("trancate", "***");
        str = str.replaceAll("char", "***");
        return str;
    }

    /**
     * 检查SQL注入
     *
     * @param value 参数值
     * @throws IOException IO异常
     */
    private String checkSqlInject(String value) {
        if (null != value) {
            return dostring(value);
        }
        return null;
    }


    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes("UTF-8"));
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }

            @Override
            public int read() {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream(), Charsets.UTF_8));
    }

    public String getBody() {
        return this.body;
    }


    @Override
    public String getParameter(String name) {
        return super.getParameter(name);
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return super.getParameterMap();
    }

    @Override
    public Enumeration<String> getParameterNames() {
        return super.getParameterNames();
    }

    @Override
    public String[] getParameterValues(String name) {
        //替换 路径参数
        String[] s = new String[super.getParameterValues(name).length];
        for (int i = 0; i < super.getParameterValues(name).length; i++) {
            s[i] = checkSqlInject(super.getParameterValues(name)[i]);
        }
        return s;
    }

}