經常使用的權限系統設計模式是以角色爲核心的,即角色是具備相同權限的一類人員的集合:html
1. 一個角色能夠有包含多個操做人員,一個操做人員也能夠屬於多個角色web
2. 一個角色能夠具備多個功能的操做權限,一個功能也能夠被多個角色所擁有。數據庫
在登陸時經過查詢登陸用戶所屬角色,便可獲得個用戶的全部功能集合,以下圖:設計模式
多數業務系統的頁 面功能菜單設計是以三級爲標準的,即一級功能菜單、二級功能菜單、三級功能菜單,一般狀況下一二級功能菜單只是用於功能分類,是不具備功能訪問地址的,三 級菜單纔是功能的真正入口,常規權限系統就是經過控制每一個人員對應的功能菜單的顯示與隱藏來實現權限控制。要實現細粒度權限控制,可在設計功能表時再加入 第四層:頁面元素,隸屬於第三層功能菜單,這些頁面元素用來標識功能頁面中的每個功能按鈕,如增長、修改、刪除、查詢均可算是頁面元素,在爲角色分配權 限時,第四層也一樣歸入統一權限管理,若是有此頁面元素的權限,則頁面上就顯示該按鈕,若是沒有此頁面元素的功能權限,則該按鈕就不會顯示出來。mvc
對於沒有權限訪問的功能或頁面除了進行前臺的隱藏以外,還須要在後臺訪問時進行權限的驗證,不然操做人員繞開頁面直接經過輸入URL訪問功能就會形成權限漏洞,經過SpringMVC+Annotation的方式能夠輕鬆實現,代碼以下:app
第一步:建立SpringMVC攔截器,攔截全部須要進行權限驗證的功能請求post
<!-- 開啓註解 --> <mvc:annotation-driven/> <!-- 靜態資源訪問 --> <mvc:resources location="/static/" mapping="/static/**"/> <!-- 攔截器 --> <mvc:interceptors> <!-- 多個攔截器,順序執行 --> <mvc:interceptor> <!-- 若是不配置或/**,將攔截全部的Controller --> <mvc:mapping path="/**" /> <!-- 在Freemarker界面展現以前作一些通用處理 --> <bean class="xx.xxxx.core.web.FreeMarkerViewInterceptor"></bean> </mvc:interceptor> </mvc:interceptors>
第二步:建立做用於Method級別的Annotation類,用於傳入功能IDspa
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Permission { /** * 功能ID,該功能ID,對應數據庫中的功能ID * @return * @version V1.0.0 * @date Jan 13, 2014 4:59:35 PM */ String value(); }
第三步:經過靜態常量創建數據庫中的功能ID與執行方法的一對一關係設計
public class FuncConstants { /** * 系統管理-角色管理-增長角色 */ public final static String Xtgl_Jsgl_AddJs = "4399d98bb0d84114acb5693081e83bc9"; /** * 系統管理 - 部門管理- 部門列表 */ public final static String Xtgl_Bmgl_BmList = "dbc4bf80f8b6418788b79de204d37932"; }
第四步:在SpringMVC攔截器中驗證權限code
/** * FreeMarker視圖攔截器,頁面展現以前作一些通用處理 * @version V1.0.0 * @date Dec 12, 2013 4:20:04 PM */ public class FreeMarkerViewInterceptor extends HandlerInterceptorAdapter { public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3) throws Exception { } public void postHandle(HttpServletRequest request, HttpServletResponse response, Object arg2, ModelAndView view) throws Exception { String contextPath = request.getContextPath(); if (view != null) { request.setAttribute("base", contextPath); } } public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //處理Permission Annotation,實現方法級權限控制 HandlerMethod method = (HandlerMethod)handler; Permission permission = method.getMethodAnnotation(Permission.class); //若是爲空在表示該方法不須要進行權限驗證 if (permission == null) { return true; } //驗證是否具備權限 if (!WebUtil.hasPower(request, permission.value())) { response.sendRedirect(request.getContextPath()+"/business/nopermission.html"); return false; } return true; //注意此處必須返回true,不然請求將中止 //return true; } }
至此,基於按鈕、方法驗證的細粒度權限體系完成!