對(duì)大部分系統(tǒng)來說都需要權(quán)限管理來決定不同用戶可以看到哪些內(nèi)容,那么如何在Spring MVC中實(shí)現(xiàn)權(quán)限驗(yàn)證呢?當(dāng)然我們可以繼續(xù)使用servlet中的過濾器Filter來實(shí)現(xiàn)。但借助于Spring MVC中的action攔截器我們可以實(shí)現(xiàn)注解式的權(quán)限驗(yàn)證。
一.首先介紹一下action攔截器:
HandlerInterceptor是Spring MVC為我們提供的攔截器接口,來讓我們實(shí)現(xiàn)自己的處理邏輯,HandlerInterceptor 的內(nèi)容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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個(gè)方法,其含義如下:
preHandle:在執(zhí)行action里面的處理邏輯之前執(zhí)行,它返回的是boolean,這里如果我們返回true在接著執(zhí)行postHandle和afterCompletion,如果我們返回false則中斷執(zhí)行。
postHandle:在執(zhí)行action里面的邏輯后返回視圖之前執(zhí)行。
afterCompletion:在action返回視圖后執(zhí)行。
HandlerInterceptorAdapter適配器是Spring MVC為了方便我們使用HandlerInterceptor而對(duì)HandlerInterceptor 的默認(rèn)實(shí)現(xiàn),里面的3個(gè)方法沒有做任何處理,在preHandle方法直接返回true,這樣我們繼承HandlerInterceptorAdapter后只需要實(shí)現(xiàn)3個(gè)方法中我們需要的方法即可,而不像繼承HandlerInterceptor一樣不管是否需要3個(gè)方法都要實(shí)現(xiàn)。
當(dāng)然借助于HandlerInterceptor我們可以實(shí)現(xiàn)很多其它功能,比如日志記錄、請(qǐng)求處理時(shí)間分析等,權(quán)限驗(yàn)證只是其中之一。
二.下面我們就來一步一步來完成注解式權(quán)限驗(yàn)證的功能。
首先添加一個(gè)賬戶的Controller和登錄的Action及視圖來模擬在沒有權(quán)限時(shí)跳轉(zhuǎn)到登陸頁面,內(nèi)容分別如下:
com.demo.web.controllers包中的AccountController.java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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:
1
2
3
4
5
6
7
8
9
10
11
12
|
<%@ 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> |
新建包c(diǎn)om.demo.web.auth,添加自定義注解AuthPassport,內(nèi)容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
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 ; } |
添加自己的攔截器實(shí)現(xiàn)AuthInterceptor繼承于HandlerInterceptorAdapter,內(nèi)容如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
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 ); //沒有聲明需要權(quán)限,或者聲明不驗(yàn)證權(quán)限 if (authPassport == null || authPassport.validate() == false ) return true ; else { //在這里實(shí)現(xiàn)自己的權(quán)限驗(yàn)證邏輯 if ( false ) //如果驗(yàn)證成功返回true(這里直接寫false來模擬驗(yàn)證失敗的處理) return true ; else //如果驗(yàn)證失敗 { //返回到登錄界面 response.sendRedirect( "account/login" ); return false ; } } } else return true ; } } |
配置項(xiàng)目的springservlet-config.xml添加如下內(nèi)容:
1
2
3
4
5
6
|
< mvc:interceptors > <!-- 國(guó)際化操作攔截器 如果采用基于(請(qǐng)求/Session/Cookie)則必需配置 --> < bean class = "org.springframework.web.servlet.i18n.LocaleChangeInterceptor" /> <!-- 如果不定義 mvc:mapping path 將攔截所有的URL請(qǐng)求 --> < bean class = "com.demo.web.auth.AuthInterceptor" ></ bean > </ mvc:interceptors > |
這樣在執(zhí)行每個(gè)action方法是都會(huì)調(diào)用AuthInterceptor處理,當(dāng)判斷action上有我們定義AuthPassport注解時(shí)就會(huì)執(zhí)行里面的權(quán)限驗(yàn)證邏輯。
運(yùn)行項(xiàng)目:
可以看到執(zhí)行了我們?cè)趕pringservlet-config.xml定義的HelloworldController的index方法。
1
2
|
<!-- 如果當(dāng)前請(qǐng)求為“/”時(shí),則轉(zhuǎn)發(fā)到“/helloworld/index" --> < mvc:view-controller path = "/" view-name = "forward:/helloworld/index" /> |
下面我們?cè)贖elloworldController的index方法上加上自定義注解AuthPassport:
1
2
3
4
5
6
7
8
9
|
@AuthPassport @RequestMapping (value={ "/index" , "/hello" }) public ModelAndView index(){ ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject( "message" , "Hello World!" ); modelAndView.setViewName( "index" ); return modelAndView; } |
重新運(yùn)行項(xiàng)目:
可以看到正確執(zhí)行了權(quán)限判斷邏輯,這樣我們只需要在我們?cè)谛枰獧?quán)限驗(yàn)證的action上加上這個(gè)注解就可以實(shí)現(xiàn)權(quán)限控制功能了。
注解式權(quán)限驗(yàn)證的內(nèi)容到此結(jié)束。
代碼下載:demo
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:http://www.cnblogs.com/liukemng/p/3751338.html