@WebFilter("/*")
public class SensitiveFilter implements Filter {
// 1.创建一个集合装敏感词汇中的数据
private List<String> list = new ArrayList<>();
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//获取所有的请求参数,如果有敏感词汇则换
// 创建代理对象
/**
* req.getClass().getClassLoader() 真实对象的类加载器
* req.getClass().getInterfaces() 真实对象所实现的所有的接口们
* InvocationHandler 实现代理
*/
ServletRequest proxy = (ServletRequest) Proxy.newProxyInstance(req.getClass().getClassLoader(), req.getClass().getInterfaces(), new InvocationHandler() {
/**
*
* @param proxy 代理对象
* @param method 代理对象执行那个方法,描述的就是哪个方法
* @param args 代理对象执行的方法的参数
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 需要进行敏感词汇过滤的方法进行增强
// 3.判断调用的方法是不是getParameter方法,如果是的话,进行增强
if (method.getName().equals("getParameter")) {
String value = (String) method.invoke(req, args);
// 判断,如果value不为空的时候,看是否包含敏感字符
// s为敏感字符 ,str为替换后的*
if (value != null) {
/* for (String s : list) {
// 判断,如果包含,则替换
if (value.contains(s)) {
String str = "";
// 判断敏感字符的长度。
for (int i = 0; i < s.length(); i++) {
str += "*";
}
value = value.replaceAll(s, str);
}
}*/
value = replaceAllSensitive(value);
}
return value;
}
// 3.判断调用的方法是不是getParameterMap方法,如果是的话,判断客户传过来的参数部位空的情况下,是否包含敏感字符,如果包含则进行替换、
if (method.getName().equals("getParameterMap")) {
// 调用真实对象调用方法,知道方法返回的是一个map的集合,强转为Map<String, String[]> map集合
Map<String, String[]> map = (Map<String, String[]>) method.invoke(req, args);
// 判断当map不为空,则对map中的参数进行判断,如果包含敏感字符,则进行替换
if (map != null) {
// 遍历获取到的每一对参数键值对
for (Map.Entry<String, String[]> entry : map.entrySet()) {
// 获取到每一个请求参数的值
String[] values = entry.getValue();
// 遍历所有敏感字符,看参数中是否包含,如果包含,则进行替换
/* for (String s : list) {
// 判断是否包含铭感字符s、如果包含则换位str “*”;
if (values[0].contains(s)) {
// 定义一个空字符串。用来根据敏感字符的字符大小个数对*进行拼接
String str = "";
// 判断字符的个数
for (int i = 0; i < s.length(); i++) {
str += "*";
}
values[0] = values[0].replaceAll(s, str);
}
}*/
replaceAllSensitive(values);
}
}
// 如果满足,则把替换后的map集合返回;
return map;
}
// 判断方法的名字是否为 如果是的话,获取他的value。然后进行判断是否包含敏感字符
if (method.getName().equals("getParameterValues")) {
// 获取values
String[] values = (String[]) method.invoke(req, args);
// 进行判断value 。
if (values[0] != null) {
/* // 遍历敏感字符
for (String s : list) {
// 判断,如果包含,则替换
if (values[0].contains(s)) {
String str = "";
// 判断敏感字符的长度。
for (int i = 0; i < s.length(); i++) {
str += "*";
}
// 敏感字符替换
values[0] = values[0].replaceAll(s, str);
}
}*/
replaceAllSensitive(values);
}
// 返回values数组进行替换
return values;
}
// 如果不满足上面的条件,正常的调用方法,正常的返回。
return method.invoke(req, args);
}
});
// 放行的时候,必须适应动态代理对象调用方法,内部则是使用真实代理调用方法,动态代理进行改造
chain.doFilter(proxy, resp);
}
public void destroy() {
}
/**
* 2.将配置文件加载进内存
*
* @param config
* @throws ServletException
*/
public void init(FilterConfig config) throws ServletException {
try {
ServletContext servletContext = config.getServletContext();
// 根据servletContext对象,获取配置文件的真实路径
String realPath = servletContext.getRealPath("/a.txt");
BufferedReader br = new BufferedReader(new FileReader(realPath));
String line;
while ((line = br.readLine()) != null) {
// 把配置文件中的所有敏感字符都添加到集合中
list.add(line);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 传入一个字符串,将字符串中的敏感字符进行替换
public void replaceAllSensitive(String value[]) {
for (String s : list) {
// 判断,如果包含,则替换
if (value[0].contains(s)) {
String str = "";
// 判断敏感字符的长度。
for (int i = 0; i < s.length(); i++) {
str += "*";
}
value[0] = value[0].replaceAll(s, str);
}
}
}
// 传入一个字符串,将字符串中的敏感字符进行替换
public String replaceAllSensitive(String value) {
for (String s : list) {
// 判断,如果包含,则替换
if (value.contains(s)) {
String str = "";
// 判断敏感字符的长度。
for (int i = 0; i < s.length(); i++) {
str += "*";
}
value = value.replaceAll(s, str);
}
}
return value;
}
}
测试代码:
@WebServlet("/servletTest")
public class ServletTest extends HttpServlet {
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);
Map<String, String[]> map = request.getParameterMap();
for (Map.Entry<String, String[]> entry : map.entrySet()) {
for (String s : entry.getValue()) {
System.out.println(entry.getKey() +":"+ s);
}
}
String[] parameterValues = request.getParameterValues("name");
String[] parameterValues2 = request.getParameterValues("msg");
for (String value : parameterValues) {
System.out.println(value);
}
for (String value : parameterValues2) {
System.out.println(value);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
代理模式的实现方式?
动态代理一个真实对象的实现步骤?
Proxy.newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h);
3个参数分别是什么意思?
ClassLoader loader:类加载器-固定写法:真实对象.getClass().getClassLoader();
Class<?>[] interfaces:真实对象实现的接口数组-固定书写:真实对象.getClass().getInterfaces();
InvocationHandler h:处理器-固定书写:new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
}}
--------------------------------------------------
当使用代理对象调用任何方法时,InvocationHandler中的invoke方法都会执行!!
--------------------------------------------------
InvocationHandler的抽象方法:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
}
3个参数分别是什么意思?
proxy:代理对象(不用)
method:使用代理对象调用的是哪个方法,那么method的描述的就是哪个方法;
args:使用代理对象调用方法时传递的参数;
学习中遇到的问题:
问题1:动态代理判断方法是否为getParameterMap 时,为什么不能遍历String[]进行设置里面的每一个值
回答:因为request真代理的getParameterMap 方法,返回的是String[] 他所对应的是checkbox复选框。
问题2,共性抽取方法,参数为数组的可以使用,参数为字符串的无法使用
之前的方法中只是在方法中执行了替换的动作,并没有真正的将结果返回。所以需要给方法添加返回值然后接收。