1. 需求描述
某内部管理系统采用Spring MVC搭建,用户可以登录系统进行CRUD以及其他的一些日常管理操作。现在希望对某些敏感操作(譬如修改重要数据)进行拦截,在日志中记录下该操作的执行人,操作时间,操作名称,传入参数以及返回结果等信息,以便万一出问题后追究查验。
2. 解决思路
有两种方案:
(1)把对应的MVC方法使用AOP去拦截,这个是方法级别的拦截;
(2)使用Spring MVC Interceptor去拦截,这个是基于URL的拦截。
那么,如何选择呢?考虑到我们这个是WEB项目,只有登录用户才能执行管理操作,而登录用户的用户信息一般放在Session里,使用基于URL拦截的方法便于提取Session数据;而且,被Spring MVC @Controller注解的类,都被AnnotationMethodHandlerAdapter给代理了,使用AOP进行拦截的话需要做些特殊处理。所以,在这里我们选择使用Interceptor拦截。
3. 具体实现
(1)Spring配置文件
在beans头部标签加入:
...
xmlns:mvc="http://www.springframework.org/schema/mvc"
...
xsi:schemaLocation="...
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
..."
然后加上mvc:interceptors拦截声明:
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/><!--拦截所有controller-->
<mvc:exclude-mapping path="/js/**" />
<mvc:exclude-mapping path="/css/**" />
<mvc:exclude-mapping path="/img/**" />
<mvc:exclude-mapping path="*.woff" />
<mvc:exclude-mapping path="*.ico" />
<mvc:exclude-mapping path="*.swf" />
<mvc:exclude-mapping path="*.png" />
<bean id="log4UpdateOrDeleteInterceptor"
class="com.XXX.testmvc.interceptor.Log4UpdateOrDeleteInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
Spring的拦截路径采用了AntPathMatcher的方式。以下是引用自官方的说明:
The mapping matches URLs using the following rules:
- ? matches one character
- * matches zero or more characters
- ** matches zero or more 'directories' in a path
Some examples:
-
com/t?st.jsp
- matches com/test.jsp
but also com/tast.jsp
or com/txst.jsp
-
com/*.jsp
- matches all .jsp
files in the com
directory
-
com/**/test.jsp
- matches all test.jsp
files underneath the com
path
-
org/springframework/**/*.jsp
- matches all .jsp
files underneath the org/springframework
path
-
org/**/servlet/bla.jsp
- matches org/springframework/servlet/bla.jsp
but also org/springframework/testing/servlet/bla.jsp
and org/servlet/bla.jsp
(2)实现拦截器
继承HandlerInterceptorAdapter并按需覆写里面的preHandle和postHandle方法即可。
/**
* 拦截敏感操作并记录到日志
*
* @author lixuanbin
*/
public class Log4UpdateOrDeleteInterceptor extends HandlerInterceptorAdapter {
protected static final Logger log = Logger.getLogger(Log4UpdateOrDeleteInterceptor.class);
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
HttpSession session = request.getSession();
String requestUri = request.getRequestURI();
log.debug("request uri:" + requestUri);
String contextPath = request.getContextPath();
String url = requestUri.substring(contextPath.length());
if (StringUtils.contains(url, "add") || StringUtils.contains(url, "edit")
|| StringUtils.contains(url, "delete")) {
String user = session.getAttribute(SessionKey.USERNAME_SESSION_NAME) != null ? (String) session
.getAttribute(SessionKey.USERNAME_SESSION_NAME) : null;
StringBuffer sb = new StringBuffer();
Enumeration<String> a = null;
a = request.getParameterNames();
while (a.hasMoreElements()) {
String key = a.nextElement();
sb.append(key + ":" + request.getParameter(key) + ", ");
}
log.warn(String.format("FBI request warning! user: %s, url: %s, params: {%s}", user,
url, StringUtils.removeEnd(StringUtils.trim(sb.toString()), ",")));
}
return true;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object o,
ModelAndView mav) throws Exception {
HttpSession session = request.getSession();
String requestUri = request.getRequestURI();
log.debug("request uri:" + requestUri);
String contextPath = request.getContextPath();
String url = requestUri.substring(contextPath.length());
if ((StringUtils.contains(url, "add") || StringUtils.contains(url, "edit") || StringUtils
.contains(url, "delete")) && mav != null) {
String user = session.getAttribute(SessionKey.USERNAME_SESSION_NAME) != null ? (String) session
.getAttribute(SessionKey.USERNAME_SESSION_NAME) : null;
Map<String, Object> map = mav.getModel();
StringBuffer sb = new StringBuffer();
for (Map.Entry<String, Object> entry : map.entrySet()) {
sb.append(entry.getKey() + ":"
+ (entry.getValue() != null ? entry.getValue().toString() : null) + ", ");
}
log.warn(String.format("FBI response warning! user: %s, url: %s, models: {%s}", user,
url, StringUtils.removeEnd(StringUtils.trim(sb.toString()), ",")));
}
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object o,
Exception excptn) throws Exception {
// System.out.println("afterCompletion");
}
}
本例检查URI是否含有敏感操作来判断是否需要进行日志记录,如果您采用了REST接口,也可以加上request method的校验。
4. 参考资料:
http://docs.spring.io/spring/docs/3.0.x/javadoc-api/org/springframework/util/AntPathMatcher.html
http://www.oschina.net/question/222929_124314
分享到:
相关推荐
Mybatis拦截器记录数据更新历史记录到MongoDB的源码,另外需要配置拦截器到mybatis配置文件中。
主要介绍了Spring MVC 拦截器 interceptor 用法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
springmvc中关于拦截器的使用
初学者很容易将 Spring MVC 拦截器 和 Spring Cloud OpenFeign 拦截器搞混,误以为OpenFeign拦截器就是SpringMVC拦截器:Spring MVC拦截器发生在客户端 和 服务端之间,在客户端向服务端发送请求时进行拦截处理。...
主要介绍了在spring-boot工程中添加spring mvc拦截器,Spring MVC的拦截器(Interceptor)不是Filter,同样可以实现请求的预处理、后处理。,需要的朋友可以参考下
主要给大家介绍了关于Spring MVC拦截器的基本使用方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring MVC具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
15.1 拦截器概述 Spring MVC中的拦截器(Interceptor)类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并作相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、判断用户是否登录等。 ...
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理,这篇文章主要介绍了详解SpringMVC中使用Interceptor拦截器,有兴趣的可以了解一下。
项目基于jdk1.8整合了springboot+mvc+mybatis(通用mapper)+druid+jsp+bootstrap等技术,springboot+Listener(监听器),Filter(过滤器),Interceptor(拦截器),Servlet,springmvc静态资源,文件上传下载,多数据源切换,缓存...
我们对拦截器并不陌生,无论是 Struts 2 还是 Spring MVC 中都提供了拦截器功能,它可以根据 URL 对请求进行拦截,主要应用于登陆校验、权限验证、乱码解决、性能监控和异常处理等功能上。Spring Boot 同样提供了...
converter 转换器 i18n struts2 spring MVC 拦截器 interceptor 过滤器 filter web.xml implements filter filterchain arg2.doFilter(req,resp); 监听器 servlet application /session /request 6/8 个 ...
弹簧方法拦截器 该示例显示了一个HandlerInterceptor来拦截Web调用并注销注释值。 此示例使用启动2,唯一的区别是您将使用WebMvcConfigurer注册拦截器。
3-8 使用Filter和Interceptor拦截REST服务 3-9 使用REST方式处理文件服务 3-10 使用多线程提高REST服务性能 3-11 使用Swagger自动生成文档 3-12 使用WireMock伪造REST服务 第4章 使用Spring Security开发基于...
项目基于jdk1.8整合了springboot+mvc+mybatis(通用mapper)+druid+jsp+bootstrap等技术,springboot+Listener(监听器),Filter(过滤器),Interceptor(拦截器),Servlet,springmvc静态资源,文件上传下载,多数据源切换,缓存...
skywalking mvn 插件 获取请求参数 头部信息 拦截spring mvc请求信息 主要在源码工程改了 org.apache.skywalking.apm.agent.core.conf.Config 和 org.apache.skywalking.apm.plugin.spring.mvc.commons.interceptor....
mybatis实战教程mybatis in action之六与Spring MVC 的集成 mybatis实战教程mybatis in action之七实现mybatis分页源码下载 mybatis实战教程mybatis in action之八mybatis 动态sql语句 mybatis实战教程mybatis in ...
项目基于jdk1.8整合了springboot+mvc+mybatis(通用mapper)+druid+jsp+bootstrap等技术,springboot+Listener(监听器),Filter(过滤器),Interceptor(拦截器),Servlet,springmvc静态资源,文件上传下载,多数据源切换,缓存...
使用Spring函数困难 通常,实现编码,CORS,XSS,LOG,证书,授权等。 拦截器 它是Spring的Spring Context的功能,是一种Bean 因为它是一个Spring容器,所以它可以注入其他bean并具有良好的可用性。 因为可以使用...
项目基于jdk1.8整合了springboot+mvc+mybatis(通用mapper)+druid+jsp+bootstrap等技术,springboot+Listener(监听器),Filter(过滤器),Interceptor(拦截器),Servlet,springmvc静态资源,文件上传下载,多数据源切换,缓存...
9.2.2 使用自动连线将依赖注入到动作、拦截器和结果 205 9.3 为什么在Struts 2中使用JPA 207 9.3.1 使用JPA和Hibernate建立项目 208 9.3.2 基于Spring管理JPA编写代码 212 9.4 小结 216 第10章 探索验证框架 217 ...