Appfuse:許可權控制

消失的風發表於2015-07-15

Appfuse的許可權控制依賴於Struts的Menu機制,common下的menu.jsp是對選單順序的定義,詳細的選單項和選單連結及許可權再menu-config.xml中控制,如下:

<Menu name="Logout" title="user.logout" page="/logout" roles="ROLE_ADMIN,ROLE_USER,ROLE_PRODUCT" />

roles中的值即是role表中的name,給那個角色分配選單的許可權,則把角色的name加入到選單定義的roles中即可。

但使用過程中會發現,這樣定義好之後選單出來是亂的,源自appfuse中的一個Bug,修改檔案navbarMenu.vm即可,如下:

 1 #macro( displayNavbarMenu $menu $count)
 2   #if ($displayer.isAllowed($menu))
 3     #set ($count = $count + 1)
 4     ## set menu title
 5     #set ($title = $displayer.getMessage($menu.title))
 6     #if (!$menu.url) #set ($url="javascript:void(0)") #else #set ($url=$menu.url) #end
 7 
 8     ## create a single menu item
 9     #if ($menu.components.size() == 0)
10         <li class="#if ($menu.name == $currentMenu)active#end">
11         <a href="$url" title="$title" #if($menu.target)target="$menu.target" #end#if($menu.width)style="width: ${menu.width}px"#end>${title}</a>
12     #else ## create multiple menu items in a menu
13         #if ($menu.components.size() > 0)
14             #set ($hasViewableChildren = false)
15             #set ($renderedChildren = 0)
16             #foreach ($menuIt in $menu.components)
17                 #if ($displayer.isAllowed($menuIt))
18                     #set($hasViewableChildren = true)
19                     #set($renderedChildren = $renderedChildren + 1)
20                 #end
21             #end
22         #end
23 
24         <li#if ($hasViewableChildren) class="dropdown#if ($menu.name == $currentMenu) active#end"#end>
25           <a href="#" title="$title"
26              #if($menu.target)target="$menu.target" #end
27              #if($menu.width)style="width: ${menu.width}px"#end
28              class="dropdown-toggle" data-toggle="dropdown">${title}</a>
29     #end
30 
31     #if ($menu.components.size() > 0)
32         #if ($hasViewableChildren)
33           <ul class="dropdown-menu">
34         #end
35 
36         #set ($count = 0)
37         #foreach ($menuIt in $menu.components)
38             #displayNavbarMenu($menuIt, $count)
39         #end
40 
41         #if ($hasViewableChildren && ($count == $renderedChildren))
42           </ul></li>
43         #else
44           </ul>
45           #if ($count > $renderedChildren)
46           </li>
47           #end
48         #end
49     #else
50       </li>
51       #if ($menu.parent && $count == $menu.parent.components.size())
52       ##</ul>
53       #end
54     #end
55   #end
56 #end
57 
58 #displayNavbarMenu($menu, 0)
navbarMenu.vm

使用Menu控制許可權只能控制到選單的可見性,如果想深入到資料控制需要自己再處理。下面是通過切入OnSubmit方法做的操作控制:

1. 首先定義切面,切入OnSubmit方法

 1 /**
 2      * 做許可權驗證,如果使用者無許可權,則拒絕請求
 3      */
 4     @Override
 5     public Object invoke(MethodInvocation invocation) throws Throwable {
 6         try {
 7             Boolean allow = false;
 8             // 當前執行的操作
 9             String action = "";
10             // 獲取當前操作的使用者的角色
11             User user = userManager.get(getCurrentUserID());
12             Set<Role> roleList = user.getRoles();
13             // 當前執行的操作,從Request中獲取
14             // 基於OnSubmit的簽名獲取RequestString onSubmit(Greatplace greatplace,
15             // BindingResult errors, HttpServletRequest request,
16             // HttpServletResponse response)
17             if (invocation.getArguments().length == 4
18                     && invocation.getArguments()[2].getClass() == HttpServletRequest.class) {
19                 HttpServletRequest request = (HttpServletRequest) invocation
20                         .getArguments()[2];
21                 if (request.getParameter("save") != null) {
22                     action = RolePermissionManager.PERMISSION_SAVE;
23                 } else if (request.getParameter("delete") != null) {
24                     action = RolePermissionManager.PERMISSION_DELETE;
25                 } else if (request.getParameter("approve") != null
26                         || request.getParameter("unapprove") != null) {
27                     action = RolePermissionManager.PERMISSION_APPROVE;
28                 }
29                 for (Role r : roleList) {
30                     allow = RolePermissionManager.hasPermission(r.getName(),
31                             action);
32                     if (allow)
33                         break;
34                 }
35                 if (!allow) {
36                     request.getSession().setAttribute("successMessages",
37                             "對不起,您無權執行該操作!");
38                     return request.getPathInfo().replace("/", "");
39                 }
40             }
41             Object result = invocation.proceed();
42             return result;
43 
44         } catch (IllegalArgumentException ex) {
45             log.error(ex);
46             throw ex;
47         }
48     }
SubmitAdvice

2. 定義自己的許可權驗證方法,下面是個簡單的示例

public class RolePermissionManager {
    /**
     * 許可權項:儲存
     */
    public static final String PERMISSION_SAVE = "save";
    /**
     * 許可權項:審批
     */
    public static final String PERMISSION_APPROVE = "approve";
    /**
     * 許可權項:刪除
     */
    public static final String PERMISSION_DELETE = "delete";
    
    /**
     * 角色:管理員
     */
    public static final String ROLE_ADMIN = "ROLE_ADMIN";
    /**
     * 角色:普通使用者
     */
    public static final String ROLE_USER = "ROLE_USER";
    

    /**
     * 基於角色的許可權矩陣
     */
    private static Map<String,List<String>> permissionList;
    
    /**
     * 初始化角色的許可權項
     */
    public  RolePermissionManager(){
    }
    /**
     * 判斷當前角色是否有指定的許可權項
     * @param roleName 角色名稱
     * @param permissionName 許可權項名稱
     * @return
     */
    public static Boolean hasPermission(String roleName,String permissionName){        
        return getPermissionList().get(roleName).contains(permissionName);
    }
    /**
     * 定義角色和許可權項的規則
     * @return
     */
    public static Map<String,List<String>> getPermissionList(){
        if(permissionList == null){
            permissionList = new HashMap<String,List<String>>();
            //定義管理員的許可權
            List<String> adminPermissionList = new ArrayList<String>();
            adminPermissionList.add(PERMISSION_SAVE);
            adminPermissionList.add(PERMISSION_APPROVE);
            adminPermissionList.add(PERMISSION_DELETE);
            permissionList.put(ROLE_ADMIN, adminPermissionList);
            //定義普通使用者的許可權
            List<String> userPermissionList = new ArrayList<String>();
            permissionList.put(ROLE_USER, userPermissionList);
        }
        return permissionList;
    }
}
RolePermissionManager

這樣基本的許可權控制目的就能達到。

關於使用者看到的資料許可權我通過url中的引數,結合search來控制,但這樣只要修改url中的引數就可越過資料許可權,有待優化。

 

相關文章