【基於角色的訪問控制RBAC】許可權與資源樹
阿新 • • 發佈:2018-12-31
基於角色的許可權訪問控制(Role-BasedAccess Control)。在RBAC中,許可權與角色相關聯,通過使使用者成為適當的角色而得到這些角色的許可權。使用者可以很容易地從一個角色被指派到另一個角色。角色可依新的需求和系統的合併而賦予新的許可權,而許可權也可根據需要而從某角色中回收。這就極大地簡化了許可權的管理。
資源樹將整個系統的功能按模組劃分,如使用者管理模組,檔案管理模組,使用者管理模組下又有管理員管理,工作單位管理,系統使用者管理等。而每一個資源模組下面,都可能有多個許可權需要控制,比如工作單位管理,至少要有最基本的檢視,修改,增加,刪除四個功能,為了讓特定的角色擁有特定的功能,我們需要對功能設定許可權,因此工作單位管理模組至少需要有以下許可權:檢視工作單位,修改工作單位,刪除工作單位,新增工作單位。因此資源與許可權的關係為:一個資源擁有多個許可權 。為了在後臺方便程式設計人員控制權限,每個許可權都會有一個許可權編碼。通常相同資源下用相同的字首來表示,比如上面那個可以用work:list,work:add,work:delete,work:edit
資源樹構建過程:
先獲取當前使用者的所有角色,從而得到使用者的所有許可權。根據許可權獲得資源resourceId列表,通過resourceId將使用者擁有的資源樹利用組合模式組合起來,傳給前端,由前端進行解析生成檢視。
後端程式碼如下:
/** * 生成使用者的資源許可權的樹結構 * @return * @throws Exception */ public List<Resource> getUserPermTree(User currentUser)throws Exception{ log.info("===生成使用者的資源許可權的樹結構==="); List<Resource> result = new ArrayList<>(); //許可權資料預處理 Map<Long, List<Permission>>permMap = new HashMap<>(50); List<Role> roles=userMapper.getRoles(currentUser.getId());//獲取使用者所有角色 List<Permission> perms=new ArrayList<>();//獲取使用者所有許可權 for(Role role:roles){ List<Permission> temp=permissionMapper.listByRole(role.getId()); perms.addAll(temp); } perms.forEach(p -> { if(!permMap.containsKey(p.getResid())) permMap.put(p.getResid(), newArrayList<>()); permMap.get(p.getResid()).add(p); }); //資源資料處理 Map<Long, Resource> resourceMap= new TreeMap<>(); Set<Long> rids=new HashSet<>(); for(Permission permission:perms){//根據許可權獲取資源id列表 rids.add(permission.getResid()); } CopyOnWriteArrayList<Resource>resources=resourceMapper.listByids(rids); for(Resource resource:resources){ getFRes(resource,resources);//尋找資源的父節點(選單頭) } resources.forEach(r -> { //將許可權與資源關聯起來 if(permMap.containsKey(r.getId())){ r.setPerms(permMap.get(r.getId())); } //清除快取帶來的影響 r.getSub().clear(); resourceMap.put(r.getId(), r); if(r.getPid() == null ||r.getPid() == 1){ result.add(r); } }); //再一次迴圈構建資源的父子關係 resources.forEach(r -> { if(r.getPid() != null && resourceMap.containsKey(r.getPid())){ Resource resource = resourceMap.get(r.getPid()); resource.getSub().add(r); } }); return result; } private void getFRes(Resource resource,List<Resource>resources){ if(resource.getPid()!=null||resource.getPid()!=1){ Resource father=resourceMapper.selectByPrimaryKey(resource.getPid()); if(father!=null&&!father.getName().equals("root")){ if(!resources.contains(father)){ resources.add(father); } getFRes(father,resources); }else{ return; } }else{ return; } }
前端jsp程式碼:
<c:forEach items="${menuList}"var="menu"> <div title="${menu.name}"data-options="iconCls:'icon-application-cascade'" style="padding:5px;" > <ul class="ui-side-tree"> <c:forEach items="${menu.sub}"var="subMenu"> <c:if test="${subMenu.sub.size()eq 0}"> <li><a href="${ctx}${subMenu.url}">${subMenu.name}</a></li> </c:if> <c:if test="${subMenu.sub.size()ne 0}"> <li> <span>${subMenu.name}</span> <ul> <c:forEachitems="${subMenu.sub}" var="sub"> <li><ahref="${ctx}${sub.url}">${sub.name}</a></li> </c:forEach> </ul> </li> </c:if> </c:forEach> </ul> </div> </c:forEach>