java.lang.IllegalStateException: 不允许修改锁定的参数映射

news2024/12/25 14:36:58

问题描述:

这个问题是在我写javaweb项目,做敏感词过滤时出现的

需求是:如果是由 getParameter(String s) 得到的数据,可以直接修改value值,将含有敏感词的部分替换为 ***

request.getParameterMap() 方法返回一个包含 HTTP 请求参数的不可修改的映射。

这样设计的主要原因是为了保护请求参数的安全性和请求的一致性。HTTP 请求参数在发送到服务器端之前已经被解析和存储起来,以供服务器端使用。如果允许修改参数值,可能会导致以下问题:

  1. 安全性问题:允许直接修改请求参数可能会导致恶意用户进行参数篡改和数据注入攻击,从而危害系统安全。

  2. 请求一致性问题:由于请求参数在多个地方会被使用,如果允许修改参数值,可能会造成请求的不一致性,导致系统无法准确处理请求。

因此,为了保持请求参数的完整性和安全性,request.getParameterMap() 方法返回的映射是不可修改的。

 

错误代码:

if (method.getName().equals("getParameterMap"))
                {
                    Map map = (Map) method.invoke(servletRequest, args);//通过getParameterMap获取到的map是不允许修改的
                    if (map != null)
                    {
                        Set set = map.keySet();
                        for (Object o : set)
                        {
                            String key = (String) o;
                            String[] value = (String[]) map.get(key);
                            //增强for一般不用来增加和删除
                            for (String s : vocabularyList)
                            {
                                if (value[0].contains(s))
                                {
//                                    value[0] = value[0].replaceAll(s, "***");//这里内容没有修改,原因应该也是不允许修改参数映射
                                    value[0] = "***";
                                    map.put(key, value);//这里java.lang.IllegalStateException: 不允许修改锁定的参数映射
                                }
                                return map;
                            }
                        }
                    }
                }

解决方案是:用HashMap(Map m),重新new一个map,在新的map中修改值,并返回新的map

if (method.getName().equals("getParameterMap"))
                {
                    Map old = (Map) method.invoke(servletRequest, args);
                    //增强返回值
                    Map<String, String[]> values = new HashMap(old); //获取返回值
                    if (!values.isEmpty())
                    {
                        for (String key : values.keySet())
                        {
                            String[] value = values.get(key);
                            for (String str : vocabularyList)
                            {
                                if (value[0].contains(str))
                                { //只取String[]的第一个值
                                    value[0] = value[0].replaceAll(str, "***");
                                    values.put(key, value);
                                }
                            }
                        }
                    }
                    return values;
                }

完整的代码:


@WebFilter("/*")
public class SensitiveVocabularyFilter implements Filter {
    private final ArrayList<String> vocabularyList = new ArrayList<String>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        BufferedReader br = null;
        try
        {
            //获取txt的文件位置
            String realPath = filterConfig.getServletContext().getRealPath("/WEB-INF/classes/敏感词汇.txt");
            //读取文件
            br = new BufferedReader(new FileReader(realPath));
            //将读取的每一行数据添加到vocabularyList中
            String line = null;
            while ((line = br.readLine()) != null)
            {
                vocabularyList.add(line);
            }

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                assert br != null;
                br.close();
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        System.out.println(vocabularyList);
    }


    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
    {
        //1.创建代理对象,增强getParameter方法
        ServletRequest proxy_request = (ServletRequest) Proxy.newProxyInstance(servletRequest.getClass().getClassLoader(), servletRequest.getClass().getInterfaces(), new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
            {
                //执行处理逻辑,增强Parameter方法
                if (method.getName().equals("getParameter"))
                {
                    //如果我取到的参数值和敏感词汇中的相同,则需要将这个值改为***
                    String value = (String) method.invoke(servletRequest, args);
                    //如果获取的参数不为空
                    if (value != null)
                    {
                        for (String vocabulary : vocabularyList)
                        {
                            if (value.contains(vocabulary))
                            {
                                value = value.replaceAll(vocabulary, "***");
                            }
                        }
                        return value;
                    }
                }
                //判断方法名是否是 getParameterMap
               /* if (method.getName().equals("getParameterMap"))
                {
                    Map map = (Map) method.invoke(servletRequest, args);//通过getParameterMap获取到的map是不允许修改的
                    if (map != null)
                    {
                        Set set = map.keySet();
                        for (Object o : set)
                        {
                            String key = (String) o;
                            String[] value = (String[]) map.get(key);
                            //增强for一般不用来增加和删除
                            for (String s : vocabularyList)
                            {
                                if (value[0].contains(s))
                                {
                                    value[0] = value[0].replaceAll(s, "***");//java.lang.IllegalStateException: 不允许修改锁定的参数映射
//                                    value[0] = "***";
                                    map.put(key, value);//这里java.lang.IllegalStateException: 不允许修改锁定的参数映射
                                }
                                return map;
                            }
                        }
                    }
                }*/

                //判断方法名是否是 getParameterMap
                //解决:new一个新的map

                if (method.getName().equals("getParameterMap"))
                {
                    Map old = (Map) method.invoke(servletRequest, args);
                    //增强返回值
                    Map<String, String[]> values = new HashMap(old); //获取返回值
                    if (!values.isEmpty())
                    {
                        for (String key : values.keySet())
                        {
                            String[] value = values.get(key);
                            for (String str : vocabularyList)
                            {
                                if (value[0].contains(str))
                                { //只取String[]的第一个值
                                    value[0] = value[0].replaceAll(str, "***");
                                    values.put(key, value);
                                }
                            }
                        }
                    }
                    return values;
                }

                //判断方法名是否是 getParameterValue
                if (method.getName().equals("getParameterValues"))
                {
                    String[] value = (String[]) method.invoke(servletRequest, args);

                    //需要把敏感词汇txt每一行的字符都搞到一个字符串数组中
                    if (value != null)
                    {
                        for (String str : vocabularyList)
                        {
                            for (int i = 0; i < value.length; i++)
                            {
                                if (value[i].contains(str))
                                {
                                    value[i].replaceAll(str, "***");
                                }
                            }
                        }
                    }
                    return value;
                }

                return method.invoke(servletRequest, args);
            }
        });
        //2.放行
        filterChain.doFilter(proxy_request, servletResponse);
    }

    @Override
    public void destroy()
    {

    }
}

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

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

相关文章

三、 mysql 事务

三、 mysql 事务 061 什么是数据库事务&#xff1f;事务的特性是什么&#xff1f; 事务&#xff1a; 是数据库操作的最小工作单元&#xff0c;是作为单个逻辑工作单元执行的一系列操作&#xff1b; 这些操作作为一个整体一起向系统提交&#xff0c;要么都执行、要么都不执行&am…

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

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

Java分布式微服务1——注册中心(Eureka/Nacos)

文章目录 基础知识注册中心Eureka注册中心与Ribbon负载均衡1、Eureka注册中心2、Eureka的搭建3、Eureka服务注册4、复制服务实例5、拉取服务6、Ribbon负载均衡的流程及Eureka规则调整&#xff1a;7、Ribbon负载均衡饥饿加载 Nacos注册中心1、服务端Nacos安装与启动2、客户端Nac…

MinIO:微服务中上传图片流程

1、在nacos中配置minio参数 2、controller层 package com.heima.wemedia.controller.v1;import com.heima.model.common.dtos.ResponseResult; import com.heima.wemedia.service.WmMaterialService; import org.springframework.beans.factory.annotation.Autowired; import …

瑞数系列及顶像二次验证LOGS

瑞数商标局药监局专利局及顶像二次验证 日期&#xff1a;20230808 瑞数信息安全是一个专注于信息安全领域的公司&#xff0c;致力于为企业和个人提供全面的信息安全解决方案。他们的主要业务包括网络安全、数据安全、应用安全、云安全等方面的服务和产品。瑞数信息安全拥有一支…

AMASS database

AMASS是一个由不同的光学标记运动捕捉数据集统一表示在一个公共框架和参数化下的大型人体运动数据库。它包含了超过40小时的运动数据&#xff0c;涵盖了300多个主体和11000多个运动。它使用了SMPL人体模型&#xff0c;它是一种基于混合形状和姿态空间的生成式人体模型&#xff…

用html+javascript打造公文一键排版系统15:一键删除所有空格

现在我们来实现一键删除所有空格的功能。 一、使用原有的代码来实现&#xff0c;测试效果并不理想 在这之前我们已经为String对象编写了一个使用正则表达式来删除所有空格的方法&#xff1a; //功能&#xff1a;删除字符串中的所有空格 //记录&#xff1a;20230726创建 Stri…

WPF上位机9——Lambda和Linq

Lambda Linq 操作集合 使用类sql形式查询 Linq To SQL

PCB电路板设计基础入门学习笔记

文章目录&#xff1a; 一&#xff1a;Arduino线路板绘制&#xff08;原理图库、PCB库、原理图、PCB图绘制&#xff09; 1.原理图库绘制Schematic Library&#xff08;有现成库&#xff0c;没有就自己画&#xff09;[SCH Library] 方法一&#xff1a;自己依次画 ATMEGA328P-…

滑动窗口(全面清晰/Java)

数组模拟单调队列 分析 以k3举例&#xff1a; (1)利用单调队列的性质&#xff1a; <1>最小值&#xff1a;确保队列单调递增&#xff0c;处理后&#xff0c;队头即是最小值。 <2>最大值&#xff1a;确保队列单调递减&#xff0c;处理后&#xff0c;队头即是最大值…

【CSS】文本效果

文本溢出、整字换行、换行规则以及书写模式 代码&#xff1a; <style> p.test1 {white-space: nowrap; width: 200px; border: 1px solid #000000;overflow: hidden;text-overflow: clip; }p.test2 {white-space: nowrap; width: 200px; border: 1px solid #000000;ove…

Prometheus技术文档--基本安装-docker安装并挂载数据卷-《十分钟搭建》

一、查看可安装的版本 docker search prom/prometheus 二、拉取镜像 docker pull prom/prometheus 三、查看镜像 docker images 四、书写配置文件-以及创建挂载目录 宿主机挂载目录位置&#xff1a; 以及准备对应的挂载目录&#xff1a; /usr/local/docker/promethues/se…

【LeetCode每日一题】——219.存在重复元素II

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 哈希表 二【题目难度】 简单 三【题目编号】 219.存在重复元素II 四【题目描述】 给你一个…

[考研机试] KY20 完数VS盈数 清华大学复试上机题 C++实现

描述 一个数如果恰好等于它的各因子(该数本身除外)子和&#xff0c;如&#xff1a;6321。则称其为“完数”&#xff1b;若因子之和大于该数&#xff0c;则称其为“盈数”。 求出2到60之间所有“完数”和“盈数”。 输入描述&#xff1a; 题目没有任何输入。 输出描述&#…

体验自制免费开源闯关学SQL

文章目录 前言mac安装nodejs启动体验 前言 sql是常用必不可少的一种语言&#xff0c;我们都或有各种各样的学习经历&#xff0c;最近看鱼皮大佬开源了一款自制的闯关学SQL项目&#xff0c;该项目是纯前端语言&#xff0c;不需要太多依赖以及前置知识&#xff0c;直接下载就可以…

flutter开发实战-video_player视频播放功能及视频缓存

flutter开发实战-video_player视频播放功能及视频缓存 最近开发过程中video_player播放视频&#xff0c; 一、引入video_player 在pubspec.yaml引入video_player video_player: ^2.7.0在iOS上&#xff0c;video_player使用的是AVPlayer进行播放。 在Android上&#xff0c;…

python中文官网下载安装,python官方中文文档下载

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python官网下载步骤图解&#xff0c;python官方中文文档下载&#xff0c;现在让我们一起来看看吧&#xff01; python官网网址 python官方网站 python官网网址中文。像我们想要抓住一门好的编程语言&#xff0c;如何开始…

Yolov5缺陷检测/目标检测 Jetson nx部署Triton server

使用AI目标检测进行缺陷检测时&#xff0c;部署到Jetson上即小巧算力还高&#xff0c;将训练好的模型转为tensorRT再部署到Jetson 上供http或GRPC调用。1 Jetson nx 刷机 找个ubuntu 系统NVIDIA官网下载安装Jetson 的sdkmanager一步步刷机即可。 本文刷的是JetPack 5.1, 其中包…

PS透明屏,在科技展示中,有哪些优点展示?

PS透明屏是一种新型的显示技术&#xff0c;它将传统的显示屏幕与透明材料相结合&#xff0c;使得屏幕能够同时显示图像和透过屏幕看到背后的物体。 这种技术在商业展示、广告宣传、产品展示等领域有着广泛的应用前景。 PS透明屏的工作原理是利用透明材料的特性&#xff0c;通…

(树) 剑指 Offer 36. 二叉搜索树与双向链表 ——【Leetcode每日一题】

❓ 剑指 Offer 36. 二叉搜索树与双向链表 难度&#xff1a;中等 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个 排序的循环双向链表。要求不能创建任何新的节点&#xff0c;只能调整树中节点指针的指向。 为了让您更好地理解问题&#xff0c;以下面的二叉搜索树为…