当前位置: 首页 > news >正文

基础算法10:过滤器(Filter)对指定路径不进行过滤

(1)在web.xml中配置这样一个过滤器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!-- 过滤XSS -->
< filter >
     < filter-name >xssFilter</ filter-name >
     < filter-class >cn.zifangsky.filter.XSSFilter</ filter-class >
     < init-param >
         < param-name >exclude</ param-name >
         < param-value >/;/scripts/*;/styles/*;/images/*</ param-value >
     </ init-param >
</ filter >
< filter-mapping >
     < filter-name >xssFilter</ filter-name >
     < url-pattern >*.html</ url-pattern >
     <!-- 直接从客户端过来的请求以及通过forward过来的请求都要经过该过滤器 -->
     < dispatcher >REQUEST</ dispatcher >
     < dispatcher >FORWARD</ dispatcher >
</ filter-mapping >

(2)过滤器XSSFilter.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package  cn.zifangsky.filter;
 
import  java.io.IOException;
import  java.util.Enumeration;
import  java.util.Map;
import  java.util.Vector;
import  java.util.regex.Pattern;
 
import  javax.servlet.FilterChain;
import  javax.servlet.ServletException;
import  javax.servlet.http.HttpServletRequest;
import  javax.servlet.http.HttpServletRequestWrapper;
import  javax.servlet.http.HttpServletResponse;
 
import  org.apache.commons.lang3.StringEscapeUtils;
import  org.apache.commons.lang3.StringUtils;
import  org.springframework.web.filter.OncePerRequestFilter;
 
public  class  XSSFilter  extends  OncePerRequestFilter {
     private  String exclude =  null ;   //不需要过滤的路径集合
     private  Pattern pattern =  null ;   //匹配不需要过滤路径的正则表达式
     
     public  void  setExclude(String exclude) {
         this .exclude = exclude;
         pattern = Pattern.compile(getRegStr(exclude));
     }
     
     /**
      * XSS过滤
      */
     protected  void  doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
             throws  ServletException, IOException {
         String requestURI = request.getRequestURI();
         if (StringUtils.isNotBlank(requestURI))
             requestURI = requestURI.replace(request.getContextPath(), "" );
         
         if (pattern.matcher(requestURI).matches())
             filterChain.doFilter(request, response);
         else {
             EscapeScriptwrapper escapeScriptwrapper =  new  EscapeScriptwrapper(request);
             filterChain.doFilter(escapeScriptwrapper, response);
         }
     }
     
     /**
      * 将传递进来的不需要过滤得路径集合的字符串格式化成一系列的正则规则
      * @param str 不需要过滤的路径集合
      * @return 正则表达式规则
      * */
     private  String getRegStr(String str){
         if (StringUtils.isNotBlank(str)){
             String[] excludes = str.split( ";" );   //以分号进行分割
             int  length = excludes.length;
             for ( int  i= 0 ;i<length;i++){
                 String tmpExclude = excludes[i];
                 //对点、反斜杠和星号进行转义
                 tmpExclude = tmpExclude.replace( "\\" "\\\\" ).replace( "." "\\." ).replace( "*" ".*" );
 
                 tmpExclude =  "^"  + tmpExclude +  "$" ;
                 excludes[i] = tmpExclude;
             }
             return  StringUtils.join(excludes,  "|" );
         }
         return  str;
     }
     
     /**
      * 继承HttpServletRequestWrapper,创建装饰类,以达到修改HttpServletRequest参数的目的
      * */
     private  class  EscapeScriptwrapper  extends  HttpServletRequestWrapper{
         private  Map<String, String[]> parameterMap;   //所有参数的Map集合
         public  EscapeScriptwrapper(HttpServletRequest request) {
             super (request);
             parameterMap = request.getParameterMap();
         }
         
         //重写几个HttpServletRequestWrapper中的方法
         /**
          * 获取所有参数名
          * @return 返回所有参数名
          * */
         @Override
         public  Enumeration<String> getParameterNames() {
             Vector<String> vector =  new  Vector<String>(parameterMap.keySet());
             return  vector.elements();
         }
         
         /**
          * 获取指定参数名的值,如果有重复的参数名,则返回第一个的值
          * 接收一般变量 ,如text类型
         
          * @param name 指定参数名
          * @return 指定参数名的值
          * */
         @Override
         public  String getParameter(String name) {
             String[] results = parameterMap.get(name);
             if (results ==  null  || results.length <=  0 )
                 return  null ;
             else {
                 return  escapeXSS(results[ 0 ]);
             }
         }
 
         /**
          * 获取指定参数名的所有值的数组,如:checkbox的所有数据
          * 接收数组变量 ,如checkobx类型
          * */
         @Override
         public  String[] getParameterValues(String name) {
             String[] results = parameterMap.get(name);
             if (results ==  null  || results.length <=  0 )
                 return  null ;
             else {
                 int  length = results.length;
                 for ( int  i= 0 ;i<length;i++){
                     results[i] = escapeXSS(results[i]);
                 }
                 return  results;
             }
         }
         
         /**
          * 过滤字符串中的js脚本
          * 解码:StringEscapeUtils.unescapeXml(escapedStr)
          * */
         private  String escapeXSS(String str){
//          return StringEscapeUtils.escapeXml(StringEscapeUtils.escapeEcmaScript(str));
             return  StringEscapeUtils.escapeXml(str);
         }
     }
 
}

当然,我这里主要说的是如何将在web.xml中配置的不需要过滤的路径集合转换为正则匹配模式,如果把相关代码抽出来就是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import  java.util.regex.Pattern;
 
import  org.apache.commons.lang3.StringUtils;
 
public  class  Demo3 {
     private  static  String getRegStr(String str){
         if (StringUtils.isNotBlank(str)){
             String[] excludes = str.split( ";" );   //以分号进行分割
             int  length = excludes.length;
             for ( int  i= 0 ;i<length;i++){
                 String tmpExclude = excludes[i];
                 //对点、反斜杠和星号进行转义
                 tmpExclude = tmpExclude.replace( "\\" "\\\\" ).replace( "." "\\." ).replace( "*" ".*" );
 
                 tmpExclude =  "^"  + tmpExclude +  "$" ;
                 excludes[i] = tmpExclude;
             }
             return  StringUtils.join(excludes,  "|" );
         }
         return  str;
     }
     
     public  static  void  main(String[] args) {
         String t1 =  "/;/scripts/*;/styles/*;/images/*" ;
         String t2 =  "*/js/*;/scripts/*;" ;
         String t3 =  "\\;\\scripts\\*" ;
         String t4 =  "*" ;
         String t5 =  "/pages/*/js/*" ;
         String t6 =  "/page.html/js/*" ;
         
         String test =  "/pages/scripts/xx.js" ;
         Pattern pattern = Pattern.compile(Demo3.getRegStr(t1));
         if (pattern.matcher(test).matches()){
             System.out.println( "该路径不需要过滤" );
//          filterChain.doFilter(request, response);
         } else {
             System.out.println( "需要过滤处理" );
//          EscapeScriptwrapper escapeScriptwrapper = new EscapeScriptwrapper(request);
//          filterChain.doFilter(escapeScriptwrapper, response);
         }
             
     }
 
}

代码很简单,因此这里就不多做解释了



本文转自 pangfc 51CTO博客,原文链接:http://blog.51cto.com/983836259/1862603,如需转载请自行联系原作者

相关文章:

  • Asp.net用户多次登录问题
  • 如何应对被地下的Oracle口令加密算法(1)
  • Haproxy+Keepalived+Jboss集群实施架构一例
  • Solaris10下载、安设和设置装备摆设(2)
  • 深入浅出多线程系列之六:事件驱动异步模式(EAP,WebClient,BackgroundWorker)
  • 小本领: 一条下令装配 Firefox 3 Beta 3
  • 因子得分
  • 红旗桌面版本最新使用要领和标题解答100例-1
  • nginx 1.8.1安装使用
  • 利用Travis CI 让你的github项目持续构建(Node.js为例)
  • XP组件下看不到IIS
  • 一个绿色版的正则表达式测试工具
  • Git学习笔记(一)
  • C++ STL速查手册笔记
  • Flickr 网站架构分析
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • CAP 一致性协议及应用解析
  • JavaScript的使用你知道几种?(上)
  • java取消线程实例
  • MySQL常见的两种存储引擎:MyISAM与InnoDB的爱恨情仇
  • React Native移动开发实战-3-实现页面间的数据传递
  • Spring Boot快速入门(一):Hello Spring Boot
  • 聊聊redis的数据结构的应用
  • 马上搞懂 GeoJSON
  • 使用docker-compose进行多节点部署
  • 世界上最简单的无等待算法(getAndIncrement)
  • 微信小程序--------语音识别(前端自己也能玩)
  • 7行Python代码的人脸识别
  • Python 之网络式编程
  • 京东物流联手山西图灵打造智能供应链,让阅读更有趣 ...
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • ​520就是要宠粉,你的心头书我买单
  • ​secrets --- 生成管理密码的安全随机数​
  • #Ubuntu(修改root信息)
  • #图像处理
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (1)常见O(n^2)排序算法解析
  • (3)nginx 配置(nginx.conf)
  • (a /b)*c的值
  • (arch)linux 转换文件编码格式
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (经验分享)作为一名普通本科计算机专业学生,我大学四年到底走了多少弯路
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (一)Linux+Windows下安装ffmpeg
  • .Net CF下精确的计时器
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .NET Core 中的路径问题
  • .NET 编写一个可以异步等待循环中任何一个部分的 Awaiter
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET 应用启用与禁用自动生成绑定重定向 (bindingRedirect),解决不同版本 dll 的依赖问题
  • .NET 中的轻量级线程安全
  • .NET/C# 使用反射注册事件
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件
  • .NET的数据绑定
  • .NET中 MVC 工厂模式浅析