你的位置:首页 > Java教程

[Java教程]Appfuse:权限控制

Appfuse的权限控制依赖于Struts的Menu机制,common下的menu.jsp是对菜单顺序的定义,详细的菜单项和菜单链接及权限再menu-config.

<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)#end>${title}</a>12   #else ## create multiple menu items in a menu13     #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         #end21       #end22     #end23 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" #end27       #if($menu.width)#end28       class="dropdown-toggle" data-toggle="dropdown">${title}</a>29   #end30 31   #if ($menu.components.size() > 0)32     #if ($hasViewableChildren)33      <ul class="dropdown-menu">34     #end35 36     #set ($count = 0)37     #foreach ($menuIt in $menu.components)38       #displayNavbarMenu($menuIt, $count)39     #end40 41     #if ($hasViewableChildren && ($count == $renderedChildren))42      </ul></li>43     #else44      </ul>45      #if ($count > $renderedChildren)46      </li>47      #end48     #end49   #else50    </li>51    #if ($menu.parent && $count == $menu.parent.components.size())52    ##</ul>53    #end54   #end55  #end56 #end57 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 == 418           && invocation.getArguments()[2].getClass() == HttpServletRequest.class) {19         HttpServletRequest request = (HttpServletRequest) invocation20             .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") != null26             || 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中的参数就可越过数据权限,有待优化。