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

news2024/9/25 15:26:00

目录

目的

实现步骤

完整代码


目的

        在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();
            }

        };
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/854127.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

恒盛策略:早盘A股三大指数表现分化 CRO概念板块逆势涨超6%

周三&#xff08;8月9日&#xff09;&#xff0c;A股三大指数体现分化&#xff0c;到上午收盘&#xff0c;上证指数跌0.36%&#xff0c;报3249.02点&#xff1b;深证成指跌0.28%&#xff0c;创业板指涨0.24%&#xff1b;沪深两市合计成交额4550.78亿元&#xff0c;总体来看&…

DARPA-TC-engagement5-theia部分数据格式分析

转换出来的jsons数据主要分为四大类&#xff1a;Event、Subject、Object和Principal&#xff0c;分别代表系统事件、主体、客体和用户。各种大类中子类的数量&#xff0c;取决于CDM的版本。ShadeWatcher使用的是e3的数据&#xff0c;采用的是CDM18&#xff0c;而e5默认使用的是…

HTTP——十一、Web的攻击技术

HTTP 一、针对Web的攻击技术1、HTTP 不具备必要的安全功能2、在客户端即可篡改请求3、针对Web应用的攻击模式 二、因输出值转义不完全引发的安全漏洞1、跨站脚本攻击2、SQL 注入攻击3、OS命令注入攻击4、HTTP首部注入攻击5、邮件首部注入攻击6、目录遍历攻击7、远程文件包含漏洞…

Win10的日历软件中怎么新增日程安排及提醒?

在经济发展加速的时代&#xff0c;职场中做好时间管理的重要性不言而喻&#xff0c;而想要在工作中做好时间管理&#xff0c;关键在于按时完成每项日程安排。所以每天在使用win10电脑办公时新增日程安排并设置提醒不仅是非常有必要的&#xff0c;而且是提高效率和生活质量的重要…

Java课题笔记~ JavaWeb概述/开发基础

JavaWeb概述/开发基础 1.XML基础 &#xff08;1&#xff09;XML概述 &#xff08;2&#xff09;XML语法 &#xff08;3&#xff09;DTD约束 &#xff08;4&#xff09;Schema约束&#xff08;XML Schema 比 DTD 更强大&#xff09; 2.Web基础知识 Web是一个分布式的超媒…

Celery的基本使用

1.Celery介绍 1.1 Celery是什么&#xff1f; Celery是Python开发的简单、灵活可靠的、处理大量消息的分布式任务调度模块专注于实时处理的异步任务队列同时也支持任务调度 Celery本身不含消息服务&#xff0c;它使用第三方消息服务来传递任务&#xff0c;目前&#xff0c;Ce…

设置height:100%无效的原因以及两种解决方法

原因&#xff1a;我们知道在把盒子宽度自适应为浏览器窗口宽度&#xff0c;只需设置width:100%就可轻松解决问题&#xff0c;但是让盒子的高度自适应浏览窗口的高度并非那么容易&#xff0c;这是因为css内部计算的原因 <!-- 高度实际为字体大小 --> <div class"…

ElasticSearch:环境搭建步骤

1、拉取镜像 docker pull elasticsearch:7.4.0 2、创建容器 docker run -id --name elasticsearch -d --restartalways -p 9200:9200 -p 9300:9300 -v /usr/share/elasticsearch/plugins:/usr/share/elasticsearch/plugins -e "discovery.typesingle-node" elasti…

logo设计用什么工具比较好?为你推荐这9个

在海报设计工作中&#xff0c;logo设计是必不可少的一步&#xff0c;今天本文为大家推荐9个特别好用的logo生成器&#xff0c;一起来看看吧&#xff01; 1、即时设计 即时灵感是一个结合了AI技术的logo生成器&#xff0c;它无需设计师提供设计素材&#xff0c;只要在文本框中…

软件系统测试报告

1.简介 1.1.编写目的 本文档是对重庆市XXX项目验收测试所做的说明&#xff0c;为充分利用已有的软硬件资源&#xff0c;配合对系统应用模块的运行测试方案,查缺补漏完善系统的各项具体功能,保证项目的顺利进行&#xff0c;本测试报告有助于实现以下目标&#xff1a; 明确本次…

【Linux命令详解 | grep命令】 grep命令用于在文件中搜索指定模式的文本,功能强大且常用

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 使用基本模式搜索2. 忽略大小写匹配3. 反向匹配4. 递归搜索目录5. 显示文件名6. 显示行号7. 显示上下文行8. 启用扩展正则表达式9. 将模式视为固定字符串10. 使用颜色高亮显示匹配文本 总结 简介 在Linux系统中&…

12v转5v降压模块

问&#xff1a;什么是12V转5V降压模块&#xff1f;它的功能是什么&#xff1f; 答&#xff1a;12V转5V降压模块是一种电子设备&#xff0c;用于将输入电压为12V的直流电转换为输出电压为5V的直流电。它的主要功能是为电子设备提供所需的适当电压&#xff0c;以便它们能够正常运…

AI里的烟火气:实在RPA数字员工频频上岗九阳、海尔、美的等多家上市家电企业

1994年&#xff0c;九阳创始人王旭宁研发出了世界上第一台豆浆机&#xff0c;他将原本需要耗费七八个小时来泡豆子、推磨、过滤、蒸煮的时间&#xff0c;缩短到了几分钟。这是生产力的一次重大进步&#xff0c;也标志着九阳这样一家品质小家电领导品牌&#xff0c;开始走入大众…

logistic的分叉图

logistic是最基础、最常用的混沌序列。 了解其分叉图很关键。 下面&#xff0c;是混沌序列的分叉图。 分叉图是怎么得到的呢&#xff0c;实际上就是通过不断地迭代&#xff0c;观察其最终值在哪。 那到底在哪呢&#xff0c;我们分别绘制了最后20个序列的分叉图如下。 很显然…

【算法篇C++实现】五大常规算法

文章目录 &#x1f680;一、分治法⛳&#xff08;一&#xff09;算法思想⛳&#xff08;二&#xff09;相关代码 &#x1f680;二、动态规划算法⛳&#xff08;一&#xff09;算法思想⛳&#xff08;二&#xff09;相关代码 &#x1f680;三、回溯算法⛳&#xff08;一&#xf…

2000-2022年上市公司环境不确定性(原始数据+测算代码+测算结果)

2000-2022年上市公司环境不确定性指数&#xff08;含原始数据 代码和计算结果&#xff09; 1、时间&#xff1a;2000-2022年 2、指标&#xff1a;gupiao代码、名称、日期、年份、总资产净利润率ROA、营业收入、上市日期、成立日期、行业代码、年末是否ST或PT、行业、EU未调整…

【CSS3】CSS3 动画 ③ ( 动画属性 | CSS3 常见动画属性简介 | 动画属性简写方式 | 动画属性简写语法 | 使用动画制作热点地图 )

文章目录 一、CSS3 动画属性1、CSS3 常见动画属性简介2、代码示例 - CSS3 常见动画属性使用 二、CSS3 动画属性简写方式1、CSS3 动画属性简写语法2、animation 简写动画属性提示3、动画属性简写形式与原形式对比4、代码示例 - CSS3 动画属性简写示例 三、使用动画制作热点地图1…

关于在c++中使用数组名作为函数参数,或者使用数组名的地址作为函数参数问题的一些研究

前言 使用数组名作为函数参数&#xff0c;或者使用数组名的地址作为函数参数&#xff0c;常常出现于对于字符串的读入问题之中。 常有以下两种写法&#xff1a; 这是使用数组名作为函数参数 #include<cstdio> char s[100]; int main() {scanf("%s",s); }在…

Java课题笔记~ 使用 AspectJ 的 AOP 配置管理事务(掌握)

使用 XML 配置事务代理的方式的不足是&#xff0c;每个目标类都需要配置事务代 理。当目标类较多&#xff0c;配置文件会变得非常臃肿。 使用 XML 配置顾问方式可以自动为每个符合切入点表达式的类生成事务代 理。其用法很简单&#xff0c;只需将前面代码中关于事务代理的配置…

【C++】开源:CGAL计算几何库配置使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍CGAL计算几何库配置使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;…