起因

最近有需求需要把站点的所有请求做一次XSS过滤,第一反应就是用Filter来做一次入参过滤(历史原因在Spring中做比在前端处理要容易),而且需要自由设置某些路由不做过滤,所以先加了一个注解@XxsFilter,有注解的路由会经过XssFilter过滤,没有注解的不做处理。

事故

做完之后发现翻车了。

想到的思路是在注入FilterRegistrationBean时通过遍历RequestMappingHandlerMappingHandlerMethod来找到所有加了自定义注解@XxsFilter的路由,将路由参数通过FilterRegistrationBeanaddUrlPatterns添加进拦截规则中。

规则添加没有问题,出问题的是一些路由中带有PathVariable的路由无法被正常拦截,如/item/{id}/info这种路由。

历程

因为知识点不扎实,第一反应是之前使用Filter在addUrlPatterns时候都是直接添加/**.css之类的,所以直接将{id}替换成*或者\D+之类的正则就可以了。

然而,事实确实完全不会生效。

一通百度(公司的网梯子偶尔访问不到),全网基本都是教怎么添加/**.css,就和整个中文世界没有人尝试在Filter中设置正则路由拦截一样,晚上在家里Google了一下,先看到了Can i use wildcard for path variable in spring webfilter?

文章中提到Spring的PathMatch都是用的https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/util/AntPathMatcher.html,然后百般尝试,发现还是不行,答主Chandan完全是没有经过尝试只是想当然的回答。

结局

多翻了几个链接后,终于在Can we use regular expressions in web.xml URL patterns?这里看到正确答案,Filter中虽然有*这种用法,但是并不是一个正则表达式,而且Filter也并不支持使用正则表达式拦截请求。

如果需要拦截就只能在doFilter通过request.getRequestURI()获取到当前访问的URI,再通过正则表达式自行过滤,但这样如果和我最初的需求:部分路由需要过滤,就会有一些出入。

按我的需求,只能遍历所有带有@XxsFilter的路由放入一个数组,然后遍历整个数组,再通过正则匹配每个请求的request.getRequestURI()来判断是否需要进行Xss过滤。

性能损失太大了,这种思路只能放弃。

附送另外一个知识点

How do I enable a filter for url that includes a certain word?这个问题中有提到Filter(过滤器)和Interceptor(拦截器)的区别:

过滤器可以修改入参,并将修改后的入参传递给后续的步骤继续处理,而拦截器不可以