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

        };
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

flutter 没有open android module in Android studio 插件代码爆红

参考 1.结论 其实就是缺少这个文件 2.解决方案有两个 2.1 方案一 手动创建一个,命名规则是项目名字‘_android’‘.iml’ 内容如下: <?xml version"1.0" encoding"UTF-8"?> <module type"JAVA_MODULE" version"4">&l…

IoTDB在springboot2中的(二) 查询

上一章我们处理的基本的构建接入&#xff0c;以及插入的处理&#xff0c;那么接下来我们进行查询的操作处理。 我们继续在IoTDBSessionConfig工具类中加入查询的方法处理 /*** description: 根据SQL查询最新一条数据* author:zgy* param sql sql查询语句&#xff0c;count查询…

基于Java开发的企业级数字化采购系统

一、项目介绍 一款全源码可二开&#xff0c;可基于云部署、私有部署的企业级数字化采购管理系统&#xff0c;供应商全生命周期管控&#xff0c;公开询价管理&#xff0c;招标&#xff0c;定标&#xff0c;评审&#xff0c;生成订单&#xff0c;送货&#xff0c;收货全流程管理…

(十一)大数据实战——hadoop高可用之HDFS手动模式高可用

前言 本节内容我们介绍一下hadoop在手动模式下如何实现HDFS的高可用&#xff0c;HDFS的高可用功能是通过配置多个 NameNodes(Active/Standby)实现在集群中对 NameNode 的热备来解决上述问题。如果出现故障&#xff0c;如机器崩溃或机器需要升级维护&#xff0c;这时可通过此种…

【perl】报错合集

perl报错合集 &#xff08;注&#xff1a;可能会不定时更新&#xff09; 1.Name “main::x” used only once: possible typo at … 1.Name "main::x" used only once: possible typo at ...给某个变量赋值但是从来没有用它&#xff0c;或者变量之只用一次但没有…

Nginx(1)

目录 1.Nginx概述2.Nginx的特点3.Nginx主要功能1.反向代理2.负载均衡 1.Nginx概述 Nginx (engine x) 是一个自由的、开源的、高性能的HTTP服务器和反向代理服务器&#xff0c;也是一个IMAP、POP3、SMTP代理服务器。 Nginx是一个强大的web服务器软件&#xff0c;用于处理高并发…

仅使用 CSS 创建打字机动画效果

创建打字机效果比您想象的要容易。虽然实现这种效果的最常见方法是使用 JavaScript&#xff0c;但我们也可以使用纯 CSS 来创建我们的打字机动画。 在本文中&#xff0c;我们将了解如何仅使用 CSS 创建打字机动画效果。它简单、漂亮、容易。我们还将看看使用 CSS 与 JavaScrip…

百度资深PMO阚洁受邀为第十二届中国PMO大会演讲嘉宾

百度在线网络技术&#xff08;北京&#xff09;有限公司资深PMO阚洁女士受邀为由PMO评论主办的2023第十二届中国PMO大会演讲嘉宾&#xff0c;演讲议题&#xff1a;运筹于股掌之间&#xff0c;决胜于千里之外 —— 360斡旋项目干系人。大会将于8月12-13日在北京举办&#xff0c;…

大模型开发(十六):从0到1构建一个高度自动化的AI项目开发流程(中)

全文共1w余字&#xff0c;预计阅读时间约40~60分钟 | 满满干货(附代码)&#xff0c;建议收藏&#xff01; 本文目标&#xff1a;通过LtM提示流程实现自动构建符合要求的函数&#xff0c;并通过实验逐步完整测试code_generate函数功能。 代码下载点这里 一、介绍 此篇文章为…

【ChatGPT 指令大全】怎么使用ChatGPT来帮我们写作

在数字化时代&#xff0c;人工智能为我们的生活带来了无数便利和创新。在写作领域&#xff0c;ChatGPT作为一种智能助手&#xff0c;为我们提供了强大的帮助。不论是作文、文章&#xff0c;还是日常函电&#xff0c;ChatGPT都能成为我们的得力助手&#xff0c;快速提供准确的文…

HTTP——九、基于HTTP的功能追加协议

HTTP 一、基于HTTP的协议二、消除HTTP瓶颈的SPDY1、HTTP的瓶颈Ajax 的解决方法Comet 的解决方法SPDY的目标 2、SPDY的设计与功能3、SPDY消除 Web 瓶颈了吗 三、使用浏览器进行全双工通信的WebSocket1、WebSocket 的设计与功能2、WebSocket协议 四、期盼已久的 HTTP/2.01、HTTP/…

“委屈”退市,达利并不“无辜”

文 | 螳螂观察 作者 | 青月 “我吃零食&#xff0c;不是因为肚子饿&#xff0c;只是有点馋。” 第一次听到这话的时候&#xff0c;达利食品的创始者许世辉&#xff0c;还是一个平平无奇的打工人&#xff0c;和很多的工友挤在一个小宿舍里&#xff0c;而其中有位工友特别爱吃…

【并发编程】无锁环形队列Disruptor并发框架使用

Disruptor 是苹国外厂本易公司LMAX开发的一个高件能列&#xff0c;研发的初夷是解决内存队列的延识问顾在性能测试中发现竟然与10操作处于同样的数量级)&#xff0c;基于Disruptor开发的系统单线程能支撑每秒600万订单&#xff0c;2010年在QCn演讲后&#xff0c;获得了业界关注…

24届近5年东南大学自动化考研院校分析

今天给大家带来的是东南大学控制考研分析 满满干货&#xff5e;还不快快点赞收藏 一、东南大学 学校简介 东南大学是我国最早建立的高等学府之一&#xff0c;素有“学府圣地”和“东南学府第一流”之美誉。东南大学前身是创建于1902年的三江师范学堂。1921年经近代著名教育家…

本地构建包含java和maven的镜像

目录 1.前提条件 2.下载 2.1.创建Dockerfile 3.构建镜像 参考文章 1.前提条件 本地环境需要的系统和软件 win10 Docker Desktop Powershell 图1 Win10安装Docker后&#xff0c;直接在Powershell使用Docker命令 有些Developer不习惯win10系统&#xff0c;却想要使用Lin…

让三驾马车奔腾:华为如何推动空间智能化发展?

上个月&#xff0c;国务院常务会议审议通过了《关于促进家居消费的若干措施》&#xff0c;其中明确提出了“推动单品智能向全屋智能发展创新培育智能消费”“开展数字家庭建设试点”等推动全屋智能拼配发展的建议与方案。 可以说&#xff0c;以整屋为单位的空间智能品类&#x…

【Spring Boot】Thymeleaf模板引擎 — Thymeleaf页面布局

Thymeleaf页面布局 熟悉Thymeleaf的语法和表达式后&#xff0c;后面开发起来会更加得心应手。接下来好好研究一下Thymeleaf如何实现完整的Web系统页面布局。 1.引入代码片段 在模板中经常希望包含来自其他模板页面的内容&#xff0c;如页脚、页眉、菜单等。为了做到这一点&a…

2023年下半年软考初级程序员备考攻略

初级程序员考试科目包含基础知识和应用技术&#xff0c;各科目的考试形式都是笔试&#xff0c;满分均为75分。程序员考试需要各科目在一次考试中均及格才算合格&#xff0c;单科及格的成绩不保留&#xff0c;也不能转移到下次考试时使用。 这里给大家理清一个程序员考试的相关…

09. Docker Compose

目录 1、前言 2、安装Docker Compose 2.1、Docker Compose版本 2.2、下载安装 3、初试Docker Compose 3.1、传统方案部署应用 3.2、使用编排部署应用 3.3、其他命令 3.3.1、ps 3.3.2、images 3.3.3、depends_on 3.3.4、scale 4、小结 1、前言 随着应用架构的不段…

JUC并发编程(JUC核心类、TimeUnit类、原子操作类、CASAQS)附带相关面试题

目录 1.JUC并发编程的核心类 2.TimeUnit&#xff08;时间单元&#xff09; 3.原子操作类 4.CAS 、AQS机制 1.JUC并发编程的核心类 虽然java中的多线程有效的提升了程序的效率&#xff0c;但是也引发了一系列可能发生的问题&#xff0c;比如死锁&#xff0c;公平性、资源管理…