Filter敏感词汇过滤
- 对
request
对象的getParamater()
、getParameterMap()
和getParameterValues()
这三个方法进行增强,产生一个新的request对象 - 放行,传递代理对象,将新request对象传入
动态代理增强对象的功能
设计模式:通用的解决固定问题的方式
1. 装饰模式
2. 代理模式
【概念】
-
真实对象:被代理的对象
-
代理对象
-
代理模式:代理对象代理真实对象,达到增强莫实对象功能的目的
【实现方式】
-
静态代理:有一个类文件描述代理模式
-
动态代理:在内存中形成代理类
【动态代理实现步骤】
-
代理对象和真实对象实现相同的接口
-
代理对象 =
Proxy. newProxyInstance();
-
使用代理对象调用方法
-
增强方法
增强方式
-
增强参数列表
-
增强返回值类型
-
增强方法体执行逻辑
动态代理敏感词汇过滤实现
1.创建敏感词汇列表
此处一定要注意txt
文件的存放路径,否则可能导致输入流无法读取文件
【放在src下】
/WEB-INF/classes/敏感词汇.txt
【放在src下的web下的filter中】
/WEB-INF/classes/com.iqqcode.userquary.web.filter/敏感词汇.txt
【txt中自定义敏感词汇】
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 {@Overridepublic 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() {@Overridepublic 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;}//判断方法名是否是 getParameterValueif (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;}}//判断方法名是否是getParameterMapif (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>();@Overridepublic 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();}}@Overridepublic void destroy() { }
}
注意事项:
-
在使用
BufferedReader
字符缓冲输入流读取文件时,要注意编码问题 -
在放行请求时,调用chain的doFilter方法,要注意把代理对象传进去,而不是真实对象
chain.doFilter(proxy_req, resp);
-
一定要注意返回值的类型
-
request调用getParameter()方法时,返回的是String
-
调用getParameterMap方法时,返回的是Map集合,键是String,值是String类型的数组
-
调用getParameterValues()方法时,返回的是一个String类型的数组
-
3.测试
定义TestServlet类测试
@WebServlet("/testSensitiveServlet")
public class TestSensitiveServlet extends HttpServlet {@Overrideprotected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String name = request.getParameter("name");String msg = request.getParameter("msg");System.out.println(name + " : " + msg);}@Overrideprotected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}
http://localhost:8080/UserQuery/testSensitiveServlet?name=张三&msg=小鸡是菜鸡
在信息添加功能中验证
SensitiveListener放在servlet包下即可以拦截项目中的敏感词汇信息
【参考文章】:JavaEE 使用Filter实现敏感词汇过滤器