`
阅读更多

前言

 

最近做的项目中,计划使用Spring Security做权限控制,但以前大多项目都是采用spring拦截器来实现。在使用Spring Security之前,首先对spring拦截器进行总结,这有助与对Spring Security的理解。使用spring拦截器做权限控制有点千篇一律,有大量重复的工作,Spring Security其实就是把这些重复的工作抽取成为框架,方便复用。

 

Spring MVC的项目中使用Spring 拦截器做权限控制,一般会有两类拦截器:一个登录拦截器和多个权限验证拦截器。

登录拦截器拦截:所有的请求,验证用户是否登录,以及用户名密码是否正确。权限验证拦截器。

多个权限验证拦截器:不同的链接规则使用不的连接器进行拦截,并进行权限验证。

配置方式如下:

<mvc:interceptors>
    <!--登录拦截器-->
<mvc:interceptor>
    <!--拦截所有请求-->
        <mvc:mapping path="/**"/>
    <!—静态资源不需要权限验证-->
        <mvc:exclude-mapping path="/static/**"/>
        <ref bean="loginIntercepter"/>
</mvc:interceptor>
 
<!--普通拦截器 对应普通管理员-->
    <mvc:interceptor>
        <mvc:mapping path="/ update /**"/>
        <ref bean="commonIntercepter"/>
</mvc:interceptor>
 
<!--管理员拦截器 对应超级管理员-->
    <mvc:interceptor>
        <mvc:mapping path="/add/**"/>
        <mvc:mapping path="/delete/**"/>
        <ref bean="adminIntercepter"/>
</mvc:interceptor>
 
<!--省略其他拦截器-->
</mvc:interceptors>
<bean id=" loginIntercepter " class="com.xx.xx.xx" />
<bean id=" commonIntercepter " class="com.xx.xx.xx" />
<bean id=" adminIntercepter " class="com.xx.xx.xx" />

 

这里创建了三个spring 拦截器,形成一个拦截器链。正常用户请求会依次通过这三个拦截器,顺序与拦截器的定义顺序相同。对应有三个拦截器beanloginIntercepter处理登陆权限验证, commonIntercepter对应普通管理员 只允许修改数据,adminIntercepter对应超级管理员 允许新增和删除数据。

 

Spring 拦截器实现

 

Spring的拦截器实现有两种方式:

第一种方式:自定义Interceptor类要实现Spring HandlerInterceptor 接口,

第二种方式是实现SpringWebRequestInterceptor接口。

 

首先来看实现HandlerInterceptor 接口方式,该接口定义如下:

public interface HandlerInterceptor {
        boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
 
        void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView var4) throws Exception;
 
        void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception var4) throws Exception;
}
 

 

preHandle 方法:在进入具体的Controller方法之前执行。在这个方法体实现里可以做权限校验,以及其他公共检测(比如 安全校验等)。校验通过返回true,进入下一个拦截器或者直接进入Controller方法。第三个参数handler,表示待执行的Controller方法。

 

postHandle方法:在具体Controller方法方法执行完成后,视图渲染之前执行。主要用途是在视图渲染前做一些通用的准备工作,可以把一些通用的数据放到第四个参数ModelAndView对象里,供视图渲染时使用。

 

afterCompletion方法:在视图渲染完成之后执行,主要用于在返回页面之前做一些清理工作。比如最常见的使用场景:在preHandle方法中可以把用户的基本信息放到 ThreadLocal中,以便在同一次请求内的任意方法里都可以取到用户信息,由于spring mvc处理用户请求是用的线程池技术,ThreadLocal是与线程绑定的,如果不及时清理就会导致内存泄漏,这时我们必须在afterCompletion方法中调用ThreadLocal的清理方法,清除掉本次请求中的信息。

 

再来看实现WebRequestInterceptor接口方式,该接口定义如下:

public interface WebRequestInterceptor {
        void preHandle(WebRequest request) throws Exception;
 
        void postHandle(WebRequest request, ModelMap var2) throws Exception;
 
        void afterCompletion(WebRequest request, Exception var2) throws Exception;
}

 

可以看到与HandlerInterceptor 的接口定义很类似,三个主要方法名相同,只是参数有些诧异,下面分别来看WebRequestInterceptor接口的三个方法:

preHandle 方法:同样是在调用Controller方法之前执行。但这个方法没有返回值,这是与HandlerInterceptor 接口的最大区别。没有返回值,同时也没有HttpServletResponse参数,说明实现该方法无法实现对请求的拦截并返回页面,其作用仅仅局限于在进入Controller方法之前做一些通用的准备工作,比如放入一些通用的参数到WebRequest对象中,方便Controller方法执行时使用。

 

postHandle方法:作用与HandlerInterceptor postHandle方法相同,在Controller方法执行完成之后 视图渲染之前执行,主要作用是:为视图渲染做通用参数数据准备。

 

afterCompletion方法:作用与HandlerInterceptor afterCompletion方法相同,在视图渲染完成之后做一些清理工作,该方法的第一个参数是Exception类型,说明它还可以捕获到视图渲染过程中的异常,并根据异常做一些通用处理。

 

通过上述解析不难发现,如果要做权限验证和拦截 只能采用实现 HandlerInterceptor 接口的方式。实现WebRequestInterceptor接口方式,更多是用于一些通用参数准备。

 

Spring拦截器和过滤器Filter的区别

 

使用Spring拦截器做权限验证,有点类似于Struts中使用过滤器Filter进行权限验证。但他们也有区别(来自互联网):

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调。

2、拦截器在spring容器中不依赖与servlet容器,过滤器依赖于servlet容器。

3、过滤器在只在Servlet前后起作用。而拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。所以在Spring构架的程序中,要优先使用拦截器。。

4、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

5、拦截器可以获取IOC容器中的各个bean,但过滤器就不行,也就是说在拦截器里注入一个service,可以调用业务逻辑更加灵活。

 

如有不全的地方,望留言补充,谢谢!

 

 

另外使用HandlerInterceptor 拦截器做权限控制,需要自己实现用户、角色、权限管理。Spring Security可以帮助我们实现对用户、角色、权限管理的封装,简化权限控制流程,需要注意的是Spring Security使用的是一系列的Filter来实现的。下次将抽时间对如何使用Spring Security进行总结。

 

转载请注明出处:

http://moon-walker.iteye.com/blog/2395218

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics