Filter动态代理敏感词汇过滤

Filter敏感词汇过滤

  1. request对象的getParamater()getParameterMap()getParameterValues()这三个方法进行增强,产生一个新的request对象
  2. 放行,传递代理对象,将新request对象传入

Filter动态代理敏感词汇过滤_第1张图片

动态代理增强对象的功能

设计模式:通用的解决固定问题的方式
1. 装饰模式

2. 代理模式

【概念】

  1. 真实对象:被代理的对象

  2. 代理对象

  3. 代理模式:代理对象代理真实对象,达到增强莫实对象功能的目的

【实现方式】

  1. 静态代理:有一个类文件描述代理模式

  2. 动态代理:在内存中形成代理类

【动态代理实现步骤】

  1. 代理对象和真实对象实现相同的接口

  2. 代理对象 = Proxy. newProxyInstance();

  3. 使用代理对象调用方法

  4. 增强方法

增强方式

  1. 增强参数列表

  2. 增强返回值类型

  3. 增强方法体执行逻辑

动态代理敏感词汇过滤实现

1.创建敏感词汇列表

此处一定要注意txt文件的存放路径,否则可能导致输入流无法读取文件

【放在src下】

/WEB-INF/classes/敏感词汇.txt

【放在src下的web下的filter中】

/WEB-INF/classes/com.iqqcode.userquary.web.filter/敏感词汇.txt

Filter动态代理敏感词汇过滤_第2张图片

【txt中自定义敏感词汇】

Filter动态代理敏感词汇过滤_第3张图片

2. 定义敏感词汇过滤器Filter类

SensitiveListener

package com.iqqcode.userquary.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;

/**
 * @Author: Mr.Q
 * @Date: 2020-02-28 20:16
 * @Description:Filter敏感词汇过滤器
 */
@WebFilter("/*")
public class SensitiveListener implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.创建代理对象,增强getParameter方法
        ServletRequest proxy_req = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //增强getParameter方法
                //判断是否是getParameter方法
                if(method.getName().equals("getParameter")){
                    //增强返回值
                    //获取返回值
                    String value = (String) method.invoke(req,args);
                    if(value != null) {
                        for (String str : list) {
                            if(value.contains(str)){
                                value = value.replaceAll(str,"***");
                            }
                        }
                    }
                    return  value;
                }


                //判断方法名是否是 getParameterValue
                if (method.getName().equals("getParameterValues")) {
                    //获取参数的值
                    String[] values = (String[]) method.invoke(req, args);
                    //定义一个新数组
                    String[] newValues = new String[values.length];
                    //遍历数组
                    if (values != null) {
                        for (int i = 0; i < values.length; i++) {
                            for (String s : list) {
                                if (values[i].contains(s)) {
                                    newValues[i] = values[i].replaceAll(s, "***");
                                    break;
                                } else {
                                    newValues[i] = values[i];
                                }
                            }
                        }
                        return newValues;
                    }
                }

                //判断方法名是否是getParameterMap
                if (method.getName().equals("getParameterMap")) {
                    //增强getParameterMap方法
                    //获取参数
                    Map<String, String[]> map = (Map<String, String[]>) method.invoke(req, args);
                    //定义一个新的map集合
                    Map<String, String[]> newMap = new HashMap<String, String[]>();
                    Set<String> keySet = map.keySet();
                    for (String key : keySet) {
                         String[] values = map.get(key);
                        //定义一个String数组
                        String[] newValues = new String[values.length];
                        if (values != null) {
                            for (int i = 0; i < values.length; i++) {
                                //遍历集合
                                for (String s : list) {
                                    if (values[i].contains(s)) {
                                        newValues[i] = values[i].replaceAll(s, "***");
                                        break;
                                    } else {
                                        newValues[i] = values[i];
                                    }
                                }
                            }
                        }
                        newMap.put(key, newValues);
                    }
                    return newMap;
                }



                return method.invoke(req,args);
            }
        });

        //2.放行
        chain.doFilter(proxy_req, resp);
    }

    //敏感词汇集合
    private List<String> list = new ArrayList<String>();

    @Override
    public void init(FilterConfig config) throws ServletException {
        try{
            //1.获取文件真实路径
            ServletContext servletContext = config.getServletContext();
            String realPath = servletContext.getRealPath("/WEB-INF/classes/敏感词汇.txt");
            //2.读取文件
            BufferedReader br = new BufferedReader(new FileReader(realPath));
            //3.将文件的每一行数据添加到list中
            String line = null;
            while((line = br.readLine())!=null){
                list.add(line);
            }

            br.close();

            System.out.println(list);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    @Override
    public void destroy() { }
}

注意事项:

  1. 在使用BufferedReader字符缓冲输入流读取文件时,要注意编码问题

  2. 在放行请求时,调用chain的doFilter方法,要注意把代理对象传进去,而不是真实对象

    chain.doFilter(proxy_req, resp);
    
  3. 一定要注意返回值的类型

    • request调用getParameter()方法时,返回的是String

    • 调用getParameterMap方法时,返回的是Map集合,键是String,值是String类型的数组

    • 调用getParameterValues()方法时,返回的是一个String类型的数组

3.测试

定义TestServlet类测试
@WebServlet("/testSensitiveServlet")
public class TestSensitiveServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = request.getParameter("name");
        String msg = request.getParameter("msg");
        System.out.println(name + " : " + msg);

    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

http://localhost:8080/UserQuery/testSensitiveServlet?name=张三&msg=小鸡是菜鸡
E:\MarkText\Cache-img

在信息添加功能中验证

SensitiveListener放在servlet包下即可以拦截项目中的敏感词汇信息

Filter动态代理敏感词汇过滤_第4张图片
在这里插入图片描述


【参考文章】:JavaEE 使用Filter实现敏感词汇过滤器

你可能感兴趣的:(#,JavaWeb)