一,背景
这两天学习了springmvc的相关知识,企业现在项目开发提倡用springmvc、spring、mybatis整合开发。这也是这篇文章的环境。
二,目的
这篇文章主要是在我学习了springmvc的拦截器后引发的思考:利用springmvc实现项目开发中的身份认证,权限控制,导航数据,日志管理。并以此根据以前的开发经验总结了一下个人的看法。(这篇文章大部分是方法,并没有完整的开发代码)
三、springmvc的拦截器
HandlerInterceptor是Spring MVC为我们提供的拦截器接口,来让我们实现自己的处理逻辑,HandlerInterceptor 的内容如下:
public interface HandlerInterceptor {
boolean preHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler)
throws Exception;
void postHandle(
HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView)
throws Exception;
void afterCompletion(
HttpServletRequest request, HttpServletResponse response,
Object handler, Exception ex)
throws Exception;
}
可以看到接口有3个方法,其含义如下:
preHandle:在执行action里面的处理逻辑之前执行,它返回的是boolean,这里如果我们返回true在接着执行postHandle和afterCompletion,如果我们返回false则中断执行。
postHandle:在执行action里面的逻辑后返回视图之前执行。
afterCompletion:在action返回视图后执行。
HandlerInterceptorAdapter适配器是Spring MVC为了方便我们使用HandlerInterceptor而对HandlerInterceptor 的默认实现,里面的3个方法没有做任何处理,在preHandle方法直接返回true,这样我们继承HandlerInterceptorAdapter后只需要实现3个方法中我们需要的方法即可,而不像继承HandlerInterceptor一样不管是否需要3个方法都要实现。
四,身份认证
(1)需求:
1)用户请求url
2)拦截器进行拦截校验
如果请求的url是公开地址(无需登陆即可访问的url),让放行
如果用户session 不存在跳转到登陆页面
如果用户session存在放行,继续操作。
(2)实现
//进入 controller方法之前执行
//用于身份认证、身份授权
//比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
//获取请求的url
String url = request.getRequestURI();
//判断url是否是公开 地址(实际使用时将公开 地址配置配置文件中)
//这里公开地址是登陆提交的地址
if(url.indexOf("login.action")>=0){
//如果进行登陆提交,放行
return true;
}//可以通过配置去配置不需要拦截的公开地址
//判断session
HttpSession session = request.getSession();
//从session中取出用户身份信息
String username = (String) session.getAttribute("username");
if(username != null){
//身份存在,放行
return true;
}
//执行这里表示用户身份需要认证,跳转登陆页面
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
//return false表示拦截,不向下执行
//return true表示放行
return false;
}
(3)配置:
上面这个的配置:
<!--拦截器 -->
<mvc:interceptors>
<!--多个拦截器,顺序执行 -->
<!-- 登陆认证拦截器 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.demo.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- /**表示所有url包括子url路径 -->
<mvc:mapping path="/**"/>
<bean class="com.demo.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.demo.interceptor.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
可以通过配置来设置不需要拦截的公开地址:
<!--配置拦截器, 多个拦截器,顺序执行 -->
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**" />
<mvc:exclude-mapping path="/login" />
<mvc:exclude-mapping path="/logout" />
<mvc:exclude-mapping path="/logstate" />
<mvc:exclude-mapping path="/loginvalidate"/>
<mvc:exclude-mapping path="/pqms/**"/>
<bean class="interceptor.LoginIntercepter"></bean>
</mvc:interceptor>
</mvc:interceptors>
五、权限控制
现在大部分项目的权限的控制都采用的是:基于角色的访问控制(role-based access control)
(1)基于角色的访问控制的介绍:
具体参考:role-based access control
(2)权限控制的实现
具体参考:简单实现权限控制
六,导航数据
(1)导航数据其实和权限控制很类似,都是判断这人什么能干,什么不能干。但是原理是不一样的,权限控制是操作了,然后判断能不能干;而导航数据是进入系统的时候就要加载的数据。
导航数据加载实现有两张方法。
(2)方法一:
利用拦截器:在postHandle(在执行action里面的逻辑后返回视图之前执行)方法中,每次调用的时候在拦截器中加载,将数据放到model中,然后传到页面。
(3)方法二:
利用js加载:在每次访问的时候利用js动态的把导航数据加载过来,然后处理成导航数据,从而控制导航。
七,日志管理:两中实现方式
拦截器实现方式