Springboot中使用过滤器校验PSOT类型请求参数内容

目录

目的

实现步骤

完整代码


目的

        在Springboot中创建过滤器,用来过滤所有POST类型请求并获取body中的参数进行校验内容是否合法;该方法仅适用于POST类型请求,因为POST和GET请求的参数位置不一样所以处理方式也不一样,如果想要实现拦截获取GET类型请求校验参数,可以参考以下示例:

Springboot中拦截GET请求获取请求参数验证合法性icon-default.png?t=N6B9https://blog.csdn.net/weixin_45151960/article/details/132184917?spm=1001.2014.3001.5501

实现步骤

        1、创建Filter过滤器用来过滤所有请求;

        2、将PSOT类型请求中的body参数内容进行转换;

        3、处理body数据进行校验:

                3.1、当body数据仅为json对象时进行处理校验;

                3.2、当body数据仅为json数组时进行处理校验;

                3.3、当body数据为json对象且包含json数组时进行处理校验;

                3.4、当body数据为json数组且包含json对象时进行处理校验;

                

完整代码

        过滤器

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.boc.ljh.utils.Result;
import com.boc.ljh.utils.status.AppErrorCode;
import org.springframework.context.annotation.Configuration;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * @Author: ljh
 * @ClassName SqlFilter
 * @Description 过滤请求内容 防止sql注入
 * @date 2023/8/8 16:15
 * @Version 1.0
 */

@WebFilter(urlPatterns = "/*", filterName = "sqlFilter")
@Configuration
public class SqlFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setContentType("application/json;charset=utf-8");
        Result result = new Result();
        result.setStatus(500);
        result.setMessage(AppErrorCode.REQUEST_DATA_FULL.message);
        String data = JSON.toJSONString(result);
        BodyReaderRequestWrapper wrapper = null;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        if (request.getMethod().equals("POST")) {
            String contentType = request.getContentType();
            if ("application/json".equals(contentType)) {
                wrapper = new BodyReaderRequestWrapper(request);
                String requestPostStr = wrapper.getBody();
                if (requestPostStr.startsWith("{")) {
                    //解析json对象
                    boolean b = resolveJSONObjectObj(requestPostStr);
                    if (!b) {
                        response.getWriter().print(data);
                        return;
                    }
                } else if (requestPostStr.startsWith("[")) {
                    //把数据转换成json数组
                    JSONArray jsonArray = JSONArray.parseArray(requestPostStr);
                    List<String> list = JSONObject.parseArray(jsonArray.toJSONString(), String.class);
                    for (String str : list) {
                        if (str.startsWith("{")) {
                            //解析json对象
                            boolean b = resolveJSONObjectObj(requestPostStr);
                            if (!b) {
                                response.getWriter().print(data);
                                return;
                            }
                        } else {
                            boolean b = verifySql(str);
                            if (b) {
                                try {
                                    response.getWriter().print(data);
                                    return;
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                    }
                }
            } else {
                //application/x-www-form-urlencoded
                Map<String, String[]> parameterMap = request.getParameterMap();
                for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
                    //校验参数值是否合法
                    String[] value = entry.getValue();
                    for (String s : value) {
                        //校验参数值是否合法
                        boolean b = verifySql(s);
                        if (b) {
                            response.getWriter().print(data);
                            return;
                        }
                    }
                }
            }
        }
        if (wrapper == null) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            filterChain.doFilter(wrapper, servletResponse);
        }
    }

    /**
     * @Author: ljh
     * @Description: 对JSONObject对象进行递归参数解析
     * @DateTime: 14:26 2023/8/9
     * @Params:
     * @Return
     */
    private boolean resolveJSONObjectObj(String requestPostStr) {
        boolean isover = true;
        // 创建需要处理的json对象
        JSONObject jsonObject = JSONObject.parseObject(requestPostStr);
        // 获取所有的参数key
        Set<String> keys = jsonObject.keySet();
        if (keys.size() > 0) {
            for (String key : keys) {
                //获取参数名称
                String value;
                if (jsonObject.get(key) != null) {
                    value = String.valueOf(jsonObject.get(key));
                    //当value为数组时
                    if (value.startsWith("[")) {
                        //把数据转换成json数组
                        JSONArray jsonArray = JSONArray.parseArray(value);
                        for (Object o : jsonArray) {
                            if (o.toString().startsWith("{")) {
                                //解析json对象
                                boolean b = resolveJSONObjectObj(o.toString());
                                if (!b) {
                                    isover = false;
                                    break;
                                }
                            } else {
                                boolean b = verifySql(value);
                                if (b) {
                                    isover = false;
                                    break;
                                }
                            }
                        }
                    } else if (value.startsWith("{")) {
                        boolean b = resolveJSONObjectObj(value);
                        if (!b) {
                            isover = false;
                            break;
                        }
                    } else {
                        //校验参数值是否合法
                        boolean b = verifySql(value);
                        if (b) {
                            isover = false;
                            break;
                        }
                    }
                }
            }
        }
        return isover;
    }


    @Override
    public void destroy() {
    }

    /**
     * @Author: ljh
     * @Description: 校验参数非法字符
     * @DateTime: 14:26 2023/8/9
     * @Params:
     * @Return
     */
    public boolean verifySql(String parameter) {
        String s = parameter.toLowerCase();
        // 过滤掉的sql关键字,特殊字符前面需要加\\进行转义
        String badStr =
                "select|update|and|or|delete|insert|truncate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute|table|" +
                        "char|declare|sitename|xp_cmdshell|like|from|grant|use|group_concat|column_name|" +
                        "information_schema.columns|table_schema|union|where|order|by|" +
                        "'\\*|\\;|\\-|\\--|\\+|\\,|\\//|\\/|\\%|\\#";

        //使用正则表达式进行匹配
        boolean matches = s.matches(badStr);
        return matches;
    }

}

        解析body数据 工具类

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

/**
 * @Author: ljh
 * @ClassName BodyReaderRequestWrapper
 * @Description 解析body数据
 * @date 2023/8/8 16:14
 * @Version 1.0
 */

public class BodyReaderRequestWrapper extends HttpServletRequestWrapper {

    private final String body;

    public String getBody() {
        return body;
    }

    /**
     * 取出请求体body中的参数(创建对象时执行)
     *
     * @param request
     */
    public BodyReaderRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);
        StringBuilder sb = new StringBuilder();
        InputStream ins = request.getInputStream();
        BufferedReader isr = null;
        try {
            if (ins != null) {
                isr = new BufferedReader(new InputStreamReader(ins));
                char[] charBuffer = new char[128];
                int readCount;
                while ((readCount = isr.read(charBuffer)) != -1) {
                    sb.append(charBuffer, 0, readCount);
                }
            }
        } finally {
            if (isr != null) {
                isr.close();
            }
        }

        sb.toString();
        body = sb.toString();
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(this.getInputStream()));
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes());
        return 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 byteArrayIns.read();
            }

        };
    }
}

<think>好的,我现在需要回答用户关于如何在POST请求中传递参数到body部分的问题。用户还要求提供示例,并且需要引用给出的三个参考资料。首先,我得回顾一下用户提供的引用内容,确保回答准确。 首先,引用[1]提到当form的action为post时,浏览器会把数据封装到HTTP body中发送到服务器。这说明传统的表单提交方式会自动处理body参数。然后,引用[2]指出SpringCloud OpenFeign在POST请求使用@RequestParam时参数会被挂在URL上,这可能是个问题,需要注意。引用[3]展示了Express.js如何处理POST请求的body参数使用了中间件来解析JSON和URL编码数据。 用户的问题是要了解POST请求中如何传递参数到body,并需要示例。所以需要分不同场景来说明,比如表单提交、使用JavaScript的Fetch API、以及不同后端框架的处理方式。同时,需要注意不同框架或库可能存在的差异,比如引用[2]中提到的SpringMVC的坑,需要提醒用户避免错误。 接下来,我需要组织回答的结构。首先解释POST请求的body参数传递的基本概念,然后分前端和后端两部分说明。前端部分可以包括HTML表单、Fetch API的例子;后端部分可以引用给出的Express.js示例,并提到SpringMVC中的注意事项。此外,需要指出常见的编码格式,如application/x-www-form-urlencoded和application/json,并说明如何设置对应的请求头。 在引用资料时,要自然地标注引用标识,比如在讲表单提交时引用[^1],在讲SpringMVC时引用[^2],在Express.js示例时引用[^3]。同时,生成的相关问题需要围绕用户可能进一步想知道的内容,比如参数编码格式、常见错误处理、不同框架的差异等。 检查是否有遗漏的要点,比如是否需要提到其他编码类型,或者工具如Postman的用法,但根据用户提供的引用,可能不需要。但可以简要提到使用工具测试POST请求,但可能不在示例范围内。需要确保每个步骤都清晰,示例正确,并且引用正确。 最后,确保回答使用中文,数学公式正确(虽然这个问题可能不涉及数学公式,但按照系统指令检查),结构清晰,问题相关且合理。现在可以开始撰写正式的回答了。</think>### POST请求body参数传递方法详解 在POST请求中传递参数到body部分主要有三种常见方式,不同场景需要配合请求头`Content-Type`设置数据编码格式。以下分步骤说明: --- #### 一、前端参数传递方法 1. **HTML表单提交** 使用`<form>`标签时,设置`method="post"`,浏览器会自动将参数放入body: ```html <form action="/submit" method="post"> <input type="text" name="username"> <input type="password" name="password"> <button type="submit">提交</button> </form> ``` 2. **JavaScript Fetch API** 通过设置`body`字段传递参数,需明确指定`Content-Type`: ```javascript // 传递JSON格式参数 fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ key1: 'value1', key2: 'value2' }) }); // 传递URL编码参数 fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: 'param1=value1&param2=value2' }); ``` --- #### 二、后端接收参数方法 不同框架对body参数的处理方式不同: 1. **Express.js示例** 需使用中间件解析body内容,如`express.json()`和`express.urlencoded()`[^3]: ```javascript const express = require('express'); const app = express(); app.use(express.json()); // 解析JSON格式 app.use(express.urlencoded({ extended: true })); // 解析URL编码 app.post('/api', (req, res) => { const data = req.body; // 直接获取body参数 res.send(data); }); ``` 2. **SpringMVC注意事项** 避免使用`@RequestParam`接收POST参数,应使用`@RequestBody`注解处理JSON数据: ```java @PostMapping("/submit") public ResponseEntity<?> handleSubmit(@RequestBody UserDTO user) { // 处理JSON格式的body参数 } ``` --- #### 三、常见编码格式 | 编码类型 | 适用场景 | 请求头设置 | |----------------------------|-----------------------|---------------------------| | `application/json` | 复杂结构化数据(如嵌套对象) | `Content-Type: application/json` | | `application/x-www-form-urlencoded` | 简单键值对(如传统表单提交) | `Content-Type: application/x-www-form-urlencoded` | | `multipart/form-data` | 文件上传 | `Content-Type: multipart/form-data` | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想养一只!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值