一、前言
上一篇中,咱們介紹了如何使用jsp自定義標簽編寫權限框架。在jsp中,權限標簽內的內容,只有在用戶擁有權限的時候,才能夠正常的展示。
但是,如果我們想限制用戶訪問某個鏈接該怎么辦呢?
首先,我們先了解一下從瀏覽器地址欄輸入地址到頁面展現的全過程。
1、在地址欄輸入地址后,瀏覽器會想后台服務器發出請求;
2、假設后台使用springMVC+spring+mybatis框架,請求會被spring的dispatcherServlet攔截,然后根據鏈接地址調用對應的controller;
3、在controller方法中進行業務處理,然后將數據封裝到ModelMap中,並返回到jsp頁面;
至此,一個請求的全過程結束,瀏覽器渲染頁面。
我們想要限制用戶訪問某個鏈接,需要在請求到達controller前進行攔截,判斷用戶是否有權限。
在這里我們使用spring的HandlerInterceptor實現
二、自定義權限注解
首先,我們自定義注解RequirePermission,代碼如下:
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface RequirePermission { String value(); }
然后,我們實現HandlerInterceptor,代碼如下:
public class RequirePermissionHandler extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HandlerMethod myHandlerMethod = (HandlerMethod) handler;
//通過handler獲取請求對應的方法,並獲取方法上的RequirePermission注解 Annotation requirePermission = myHandlerMethod.getMethod().getAnnotation(RequirePermission.class); if (requirePermission!=null){
//如果有權限注解,獲取用戶對應的權限 Set<String> hasPermissions = (Set<String>) request.getSession().getAttribute(SESSION_ATTR_PERMISSION);
//獲取方法注解中要求的權限 String requirePermission = ((RequirePermission) requirePermission).value(); if (CollectionUtils.isEmpty(hasPermissions)||!hasPermissions.contains(requirePermission)){
//用戶沒有權限,或不包含注解要求的權限,拋出異常 throw new RequirePermissionException("user doesn't have this permission!"); } } return true; } }
1、繼承HandlerInterceptorAdapter,並重寫preHandle方法。
2、在方法中,首先判斷請求的方法時候要求權限(有RequirePermission注解的),不要求權限的,將直接訪問到controller對應的方法;要求權限的,判斷用戶是否有權限,沒有權限的將會拋出異常。異常最好自定義,這樣方便捕獲權限異常,做相應的處理。
自定義異常如下:
public class RequirePermissionException extends Exception { public RequirePermissionException(String exception){ super(exception); } public RequirePermissionException(){ super(); } }
在controller中,使用注解@ExceptionHandler捕獲權限異常,如下:
//捕獲權限異常
@ExceptionHandler(RequirePermissionException.class)
public void noPermission(HttpServletResponse response,HandlerMethod handler) throws IOException {
//跳轉權限異常地址
response.sendRedirect("/xxx/yyyy");
}
最后,我們還需在springMVC的mvc-config.xml文件配置HandlerInterceptor,使咱們自定義的HandlerInterceptor生效
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/**/*"/> <bean class="com.xx.yy.RequirePermissionHandler"/> </mvc:interceptor> </mvc:interceptors>
至此,權限的注解開發完了,我們可以在controller中非常方便的使用,控制訪問鏈接的權限。實例如下:
@RequestMapping("xxxx") @RequirePermission(value = Constants.XXX_YYY_ZZZ) public String xxxx(Integer xxxId, ModelMap map){ return "xxx/yyy"; }
我們在controller中使用@RequirePermission注解,value是這個方法要求的權限,做到了鏈接的權限控制。
到這里,自制權限框架注解就介紹完了,可擴展的地方還有很多,例如:@RequirePermission的value可以是多個權限,並且多個權限間有“與”、“或”關系,這些就留給讀者去發散,擴展了。
歡迎大家多留言,多交流,共同提高。