對大部分系統來講都須要權限管理來決定不一樣用戶能夠看到哪些內容,那麼如何在Spring MVC中實現權限驗證呢?固然咱們能夠繼續使用servlet中的過濾器Filter來實現。但藉助於Spring MVC中的action攔截器咱們能夠實現註解式的權限驗證。html
一.首先介紹一下action攔截器:java
HandlerInterceptor是Spring MVC爲咱們提供的攔截器接口,來讓咱們實現本身的處理邏輯,HandlerInterceptor 的內容以下:web
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個方法,其含義以下:spring
preHandle:在執行action裏面的處理邏輯以前執行,它返回的是boolean,這裏若是咱們返回true在接着執行postHandle和afterCompletion,若是咱們返回false則中斷執行。mvc
postHandle:在執行action裏面的邏輯後返回視圖以前執行。app
afterCompletion:在action返回視圖後執行。jsp
HandlerInterceptorAdapter適配器是Spring MVC爲了方便咱們使用HandlerInterceptor而對HandlerInterceptor 的默認實現,裏面的3個方法沒有作任何處理,在preHandle方法直接返回true,這樣咱們繼承 HandlerInterceptorAdapter後只須要實現3個方法中咱們須要的方法便可,而不像繼承HandlerInterceptor同樣不 管是否須要3個方法都要實現。ide
固然藉助於HandlerInterceptor咱們能夠實現不少其它功能,好比日誌記錄、請求處理時間分析等,權限驗證只是其中之一。post
二.下面咱們就來一步一步來完成註解式權限驗證的功能。ui
首先添加一個帳戶的Controller和登陸的Action及視圖來模擬在沒有權限時跳轉到登錄頁面,內容分別以下:
com.demo.web.controllers包中的AccountController.java:
package com.demo.web.controllers;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping(value = "/account")public class AccountController { @RequestMapping(value="/login", method = {RequestMethod.GET}) public String login(){ return "login"; } }
views文件夾下的視圖login.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body> 這裏是登陸界面</body></html>
新建包com.demo.web.auth,添加自定義註解AuthPassport,內容以下:
package com.demo.web.auth;import java.lang.annotation.Documented;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target; @Documented @Inherited @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME)public @interface AuthPassport { boolean validate() default true; }
添加本身的攔截器實現AuthInterceptor繼承於HandlerInterceptorAdapter,內容以下:
package com.demo.web.auth;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;public class AuthInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if(handler.getClass().isAssignableFrom(HandlerMethod.class)){ AuthPassport authPassport = ((HandlerMethod) handler).getMethodAnnotation(AuthPassport.class); //沒有聲明須要權限,或者聲明不驗證權限 if(authPassport == null || authPassport.validate() == false) return true; else{ //在這裏實現本身的權限驗證邏輯 if(false)//若是驗證成功返回true(這裏直接寫false來模擬驗證失敗的處理) return true; else//若是驗證失敗 { //返回到登陸界面 response.sendRedirect("account/login"); return false; } } } else return true; } }
配置項目的springservlet-config.xml添加以下內容:
<mvc:interceptors> <!-- 國際化操做攔截器 若是採用基於(請求/Session/Cookie)則必需配置 --> <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /> <!-- 若是不定義 mvc:mapping path 將攔截全部的URL請求 --> <bean class="com.demo.web.auth.AuthInterceptor"></bean></mvc:interceptors>
這樣在執行每一個action方法是都會調用AuthInterceptor處理,當判斷action上有咱們定義AuthPassport註解時就會執行裏面的權限驗證邏輯。
運行項目:
能夠看到執行了咱們在springservlet-config.xml定義的HelloworldController的index方法。
<!-- 若是當前請求爲「/」時,則轉發到「/helloworld/index" --><mvc:view-controller path="/" view-name="forward:/helloworld/index"/>
下面咱們在HelloworldController的index方法上加上自定義註解AuthPassport:
@AuthPassport @RequestMapping(value={"/index","/hello"})public ModelAndView index(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("message", "Hello World!"); modelAndView.setViewName("index"); return modelAndView; }
從新運行項目:
能夠看到正確執行了權限判斷邏輯,這樣咱們只須要在咱們在須要權限驗證的action上加上這個註解就能夠實現權限控制功能了。
註解式權限驗證的內容到此結束。