本文中介绍我在简单的实际应用中,针对登陆用户的访问权限问题的具体实现,总体设计以下图:spring
图中请求进入Spring容器后会对用户的有效性、权限进行验证,只有验证都经过以后才能进入实际业务逻辑。spring-mvc
上图的实现使用Spring MVC的HandleInterceptor、HandlerInterceptorAdapter实现,下文中将一一介绍到。mvc
HandlerInterceptor接口须要实现类管理请求执行前、执行后、和请求处理完成后所须要执行的动做。代码以下:app
public interface HandlerInterceptor { boolean preHandle(HttpServletRequest var1,HttpServletResponse var2, Object var3) throws Exception; void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception; void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception; }
preHandle
:对HTTP请求进行预处理,返回true则请求继续,返回false则须要对Response进行响应postHandle
:在HTTP请求实际业务逻辑完成后(View渲染以前),处理须要作的动做afterCompletion
:在View渲染完成以后,处理须要的动做若是操做都须要进行控制,能够直接继承该接口并一一实现其中的方法。但有些时候咱们并不须要实现这么多的操做,例如:如今我要对访问的路径进行校验,则我只须要实现preHandle
方法就能够知足,这里要用到它的适配器HandlerInterceptorAdapter
,代码以下:ide
public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor { public HandlerInterceptorAdapter() { } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return true; } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { } }
afterConcurrentHandlingStarted
:该适配器中还对当前拦截器开始执行后的动做进行了拦截处理,适用于在进行验证以前对HTTP请求作一些统一的处理接着,咱们继承该适配器并重写其中的方法就能够达到咱们的目的了,在这里以个人权限检查程序片断为例,代码以下:post
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 从请求中拿到token String account = request.getParameter(ACCOUNT_KEY); String token = request.getParameter(TOKEN_KEY); // 打印Token和请求地址 LOGGER.info("Account------->{}", account); LOGGER.info("Token--------->{}", token); LOGGER.info("ReqUrl-------->{}", request.getRequestURI()); // 任意验证属性为空->从新登陆 if (StringUtils.isEmpty(account) || StringUtils.isEmpty(token)) { response.sendRedirect(request.getContextPath() + "/err/needLogin"); return false; } // 验证用户有效性. boolean flag = validateAccount(request, account, token); if (!flag) { // 用户权限验证未经过->从新登陆 response.sendRedirect(request.getContextPath() + "/err/needLogin"); return false; } // 验证路径权限(AntPathMatcher实现) boolean authFlag = authPath(request, account); // 打印验证结果 LOGGER.info("UserAuth----->{}", flag); LOGGER.info("PathAuth----->{}", authFlag); if (flag && authFlag) { return true; } else { // 未经过路径权限验证,跳转到错误URL response.sendRedirect(request.getContextPath() + "/err/notAllow"); } return false; }
这里根据个人验证逻辑我只实现了preHandle
方法,其中使用AntPathMatcher实现路径匹配的实现会在下一篇中详细介绍。实现类完成后须要配置生效,那么在spring的配置文件中,咱们能够这么写,代码以下:设计
<!--Spring 路径拦截器配置--> <mvc:interceptors> <mvc:interceptor> <!--匹配路径--> <mvc:mapping path="/**"/> <!--从匹配路径移除不须要匹配的路径--> <mvc:exclude-mapping path="/user/login"/> <mvc:exclude-mapping path="/user/secode"/> <mvc:exclude-mapping path="/user/passwd"/> <mvc:exclude-mapping path="/err/*"/> <mvc:exclude-mapping path="/news/**"/> <!--该拦截器的实现(上面咱们完成的类)--> <bean class="cn.creditease.app.util.PathInterceptor"/> </mvc:interceptor> </mvc:interceptors>
不要忘了引入Spring Schema:code
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
这样咱们就经过Spring的拦截器实现了URL访问权限校验。xml