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()
    {

    }
}
相关推荐
drebander3 分钟前
使用 Java Stream 优雅实现List 转化为Map<key,Map<key,value>>
java·python·list
乌啼霜满天2496 分钟前
Spring 与 Spring MVC 与 Spring Boot三者之间的区别与联系
java·spring boot·spring·mvc
tangliang_cn12 分钟前
java入门 自定义springboot starter
java·开发语言·spring boot
程序猿阿伟13 分钟前
《智能指针频繁创建销毁:程序性能的“隐形杀手”》
java·开发语言·前端
Grey_fantasy22 分钟前
高级编程之结构化代码
java·spring boot·spring cloud
新知图书24 分钟前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
威威猫的栗子26 分钟前
Python Turtle召唤童年:喜羊羊与灰太狼之懒羊羊绘画
开发语言·python
力透键背26 分钟前
display: none和visibility: hidden的区别
开发语言·前端·javascript
bluefox197927 分钟前
使用 Oracle.DataAccess.Client 驱动 和 OleDB 调用Oracle 函数的区别
开发语言·c#
弗锐土豆29 分钟前
工业生产安全-安全帽第二篇-用java语言看看opencv实现的目标检测使用过程
java·opencv·安全·检测·面部