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中的参数就可越过数据权限,有待优化。
原标题:Appfuse:权限控制
关键词: