当前位置: 代码迷 >> VC/MFC >> 使用Spring MVC Interceptor阻截记录敏感操作
  详细解决方案

使用Spring MVC Interceptor阻截记录敏感操作

热度:53   发布时间:2016-05-02 03:34:19.0
使用Spring MVC Interceptor拦截记录敏感操作

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

  相关解决方案