https://mp.weixin.qq.com/s/8K5yeVQP7A1U1n9zzbxwzA
1.FIlter
Filter:JavaWeb三大组件之一,另外两个是Servlet和Listener
概念:Web中的过滤器,当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些通用的功能(登陆验证、统一编码处理、敏感字符过滤……)
1
2
3
4
5
6
7
8
9
10
11
|
Filter配置信息通常写在web.xml配置文件中
<filter>
<filter-name>xsscheck</filter-name>//名字
<filter-class>com.anbai.sec.XssFilter</filter-class>//class
</filter>
<filter-mapping>
<filter-name>xsscheck</filter-name>//名字
<!-- 拦截路径 或 匹配模式-->
<url-pattern>*.jsp</url-pattern>//路由
</filter-mapping>
|
1.1.Filter快速入门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package cn.edu.test.Filetr;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebServlet;
import java.io.IOException;
//@WebFilter表示拦截路径
@WebFilter("/*")
public class FilterDemo implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("filter...");
//一定记得放行,否则无法访问对应资源
chain.doFilter(request,response);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {}
}
|
1.2.Filter执行流程

1.3.Filter使用细节
1.3.1.Filter拦截路径配置
1
2
|
@WebFilter("/index.jsp") 拦截资源路径,不是访问路径,什么意思:可以正常访问,但是会经过过滤器拦截处理
比如这个拦截index.jsp,当你访问index.jsp时会执行filter代码,你访问login.jsp时不会执行filter代码
|

1.3.2.过滤器链
一个Web应用中,可以配置多个过滤器,这多个过滤器称为过滤器链
执行流程:从filter1入,最后从filter1出

使用注解配置Filter,优先级按照过滤器类名(字符串)的自然排序
1.4.Jeesns1.4.2-XSS跨站绕过
https://gitee.com/lxinet/jeesns
web.xml配置文件中存在XssSql的过滤器
1
2
3
4
5
6
7
8
9
|
<filter>
<filter-name>XssSqlFilter</filter-name>
<filter-class>com.lxinet.jeesns.core.filter.XssFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>XssSqlFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
|
这个过滤器的作用是拦截所有请求,每次请求前都需要XssFilter进行验证,那就查看XssFilter具体的过滤规则
chain.doFilter这个放行方法新建了一个XssWrapper对象

可以看到这个cleanXSS方法设置了一个字典,字典中全是一些能够触发XSS常用的标签,也就是黑名单过滤,对于黑名单过滤可以使用XSS字典进行Bypass

2.拦截器Interceptor
概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。
作用:拦截请求,在指定的方法调用前店,根据业务需要执行预先设定的代码。
2.1.拦截器快速入门
定义一个拦截器
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
|
package cn.edu.interceptor;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
//ctrl+o重写需要的方法
@Component
public class loginCheckInterceptor implements HandlerInterceptor {
@Override
//目标资源方法运行前运行,返回true,放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle...");
return true; //记得返回true,否则什么操作也干不了
}
@Override
//目标资源方法运行后运行,返回true,放行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
@Override
//视图渲染完毕运行,最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
preHandle:在controller方法运行前执行,所已进行校验时需要将方法写在preHandle中
postHandle&afterCompletion:在controller方法运行后执行
|
配置定义的拦截器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
package cn.edu.config;
import cn.edu.Filter.LoginCheckFilter;
import cn.edu.interceptor.loginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration //表示当前类是一个配置类
public class Webconfig implements WebMvcConfigurer {
@Autowired
private loginCheckInterceptor loginCheckInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**"); // /**表示拦截所有资源
}
}
|
2.2.拦截器拦截路径配置
1
2
3
4
5
6
7
|
addPathPatterns:拦截哪些资源
addPathPatterns("/**"):拦截所有资源
excludePathPatterns:不拦截哪些资源
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login"); // /**表示拦截所有资源
}
|

2.3.拦截器执行流程

如果一个springboot项目既有过滤器也有拦截器,先执行过滤器中放行前的逻辑,在执行拦截器中preHandle中的内容,在执行后面controller中方法,执行完成controller中方法后执行postHandle方法和afterCompletion方法,最后执行过滤器中放行后逻辑
2.4.过滤器和拦截器的区别
接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现Handlerlnterceptor接口。
拦截范围不同:过滤器Filter:会拦截所有的资源,而Interceptor只会拦截Spring环境中的资源。
过滤器放行需要执行:filterChain.doFilter(request, response);
而拦截器放行执行要执行:return true
2.5.使用拦截器完成登录校验
逻辑和过滤器一样,不同点在于放行
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
|
//ctrl+o重写需要的方法
@Slf4j
@Component
public class loginCheckInterceptor implements HandlerInterceptor {
@Override
//目标资源方法运行前运行,返回true,放行
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.获取请求url
String url = request.getRequestURL().toString();
log.info("获取请求url+{}",url);
//2.判断url是否存在login关键字,登录操作直接放行
if (url.contains("login")){
return true;
}
//不是登录操作,其它操作
//3.获取请求头中令牌token
String jwt = request.getHeader("token");
//4.判断令牌是否存在,不存在返回错误结果未登录
if (!StringUtils.hasLength(jwt)){
log.info("请求token为空,返回未登录信息");
Result result = Result.error("login error");
//手动转换为Json格式,使用Fastjson依赖
String jsonString = JSONObject.toJSONString(result);
//响应未登录结果
response.getWriter().write(jsonString);
return false;
}
//5.校验Jwt令牌,如果校验失败,返回错误结果未登录
try {
JwtUtils.parseJWT(jwt);
}catch (Exception e){
e.printStackTrace();
log.info("令牌解析失败,返回未登录信息");
Result result = Result.error("login error");
String jsonString = JSONObject.toJSONString(result);
//响应未登录结果
response.getWriter().write(jsonString);
return false;
}
//6.放行
log.info("令牌合法,放行");
return true;
}
@Override
//目标资源方法运行后运行,返回true,放行
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
@Override
//视图渲染完毕运行,最后运行
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
|