原文链接:http://lixuanbin.iteye.com/blog/2250100

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 */
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的校验。

spring拦截器的简单实现Interceptor的更多相关文章

  1. web 过滤器 Filter、 Spring 拦截器 interceptor

    1.过滤器(Filter)(在web.xml中注册过滤器) 首先说一下Filter的使用地方,我们在配置web.xml时,总会配置下面一段设置字符编码,不然会导致乱码问题: <filter> ...

  2. Java结合SpringBoot拦截器实现简单的登录认证模块

    Java结合SpringBoot拦截器实现简单的登录认证模块 之前在做项目时需要实现一个简单的登录认证的功能,就寻思着使用Spring Boot的拦截器来实现,在此记录一下我的整个实现过程,源码见文章 ...

  3. spring拦截器-过滤器的区别

    1.  理解 拦截器 :是在面向切面编程的时候,在你的 service 或者一个方法前调用一个方法,或者在方法后调用一个方法:比如动态代理就是拦截器的简单实现,在你调用方法前打印出字符串(或者做其它业 ...

  4. Spring 拦截器实现+后台原理(HandlerInterceptor)

    过滤器跟拦截器的区别 spring mvc的拦截器是只拦截controller而不拦截jsp,html 页面文件的.这就用到过滤器filter了,filter是在servlet前执行的,你也可以理解成 ...

  5. spring拦截器的定义

    (一).拦截器的定义 1.为什么需要拦截器:在做身份认证或者是进行日志的记录时,我们需要通过拦截器达到我们的目的 2.什么事拦截器:在AOP(Aspect-Oriented Programming)中 ...

  6. Spring拦截器中通过request获取到该请求对应Controller中的method对象

    背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置.我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Control ...

  7. spring拦截器中修改响应消息头

    问题描述 前后端分离的项目,前端使用Vue,后端使用Spring MVC. 显然,需要解决浏览器跨域访问数据限制的问题,在此使用CROS协议解决. 由于该项目我在中期加入的,主要负责集成shiro框架 ...

  8. Spring拦截器和过滤器

    什么是拦截器 拦截器(Interceptor): 用于在某个方法被访问之前进行拦截,然后在方法执行之前或之后加入某些操作,其实就是AOP的一种实现策略.它通过动态拦截Action调用的对象,允许开发者 ...

  9. Spring 拦截器的使用

    一.Web.xml配置 在Web.xml 配置Spring核心控制器DispatcherServlet接收所有请求 <servlet> <servlet-name>spring ...

随机推荐

  1. 损失函数 hinge loss vs softmax loss

    1. 损失函数 损失函数(Loss function)是用来估量你模型的预测值 f(x) 与真实值 Y 的不一致程度,它是一个非负实值函数,通常用 L(Y,f(x)) 来表示. 损失函数越小,模型的鲁 ...

  2. Linux 安装配置 FTP 服务 (vsftpd)

    1. 安装 vsftpd yum install vsftpd -y 2. 创建用户 record adduser -s /bin/nologin -d /var/RecordFile/ record ...

  3. 【Unity3D技术文档翻译】第1.3篇 创建 AssetBundles

    上一章:[Unity3D技术文档翻译]第1.2篇 为打包 AssetBundles 准备资产 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced ...

  4. 在gitlab上面创建私有库

    一.创建私有库1.使用xcode建立新的工程,选择Cocoa Touch Static Library,取名为podTest   WechatIMG1172.jpeg 2.创建一个类PodTest,给 ...

  5. Linux常用命令详解(二) -- 查找常用命令

    locate:    作用:在后台数据库中按文件名搜索,搜索速度更快    命令格式:locate 文件名    选项或参数:            -l    num(要显示的行数)         ...

  6. java复习笔记

    本笔记(无异常处理与网络编程部分)整理自<java程序设计>-黄岚 王岩 王康平 编著 java数据     UI     I/O      java线程      数据库操作 Java数 ...

  7. PAT 1003. Emergency 单源最短路

    思路:定义表示到达i的最短路径数量,表示到达i的最短径,表示最短路径到达i的最多人数,表示从i到j的距离, 表示i点的人数.每次从u去更新某个节点v的时候,考虑两种情况: 1.,说明到达v新的最短路径 ...

  8. JAVA 处理 Spring data mongodb 时区问题

    Spring data mongodb 查询出结果的时候会自动 + 8小时,所以我们看起来结果是对的 但是我们查询的时候,并不会自动 + 8小时,需要自己处理 解决方法 1   @JsonFormat ...

  9. Kubernetes 使用私服镜像

    非常感谢这些无私知识分享的同僚 重要参考:http://blog.csdn.net/u013812710/article/details/52766227 1.首先你得有个私库,这里我用的是阿里云私库 ...

  10. Http请求小结

    1.Http请求:get方式 public void httpGet(String url,Map<String,Object> map) { try { String joint = p ...