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

问题描述:

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

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

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

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

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

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

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

错误代码:

java 复制代码
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

java 复制代码
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;
                }

完整的代码:

java 复制代码
@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()
    {

    }
}
相关推荐
ytttr8734 小时前
隐马尔可夫模型(HMM)MATLAB实现范例
开发语言·算法·matlab
天远Date Lab4 小时前
Python实战:对接天远数据手机号码归属地API,实现精准用户分群与本地化运营
大数据·开发语言·python
listhi5204 小时前
基于Gabor纹理特征与K-means聚类的图像分割(Matlab实现)
开发语言·matlab
野生的码农4 小时前
码农的妇产科实习记录
android·java·人工智能
qq_433776425 小时前
【无标题】
开发语言·php
Davina_yu5 小时前
Windows 下升级 R 语言至最新版
开发语言·windows·r语言
阿珊和她的猫5 小时前
IIFE:JavaScript 中的立即调用函数表达式
开发语言·javascript·状态模式
毕设源码-赖学姐5 小时前
【开题答辩全过程】以 高校人才培养方案管理系统的设计与实现为例,包含答辩的问题和答案
java
listhi5206 小时前
卷积码编码和维特比译码的MATLAB仿真程序
开发语言·matlab
一起努力啊~6 小时前
算法刷题-二分查找
java·数据结构·算法