java web實(shí)現(xiàn)用戶權(quán)限管理
最近在做一個(gè)網(wǎng)站類型項(xiàng)目,主要負(fù)責(zé)后臺(tái),ui框架選型為jquery easy ui,項(xiàng)目架構(gòu)為spring mvc + spring jdbc,簡(jiǎn)單易用好上手!搭建好框架后開始了第一個(gè)任務(wù),設(shè)計(jì)并實(shí)現(xiàn)一套簡(jiǎn)單的權(quán)限管理功能。
一套最基本的權(quán)限管理包括用戶、角色、資源。
實(shí)現(xiàn)效果:
數(shù)據(jù)庫(kù)設(shè)計(jì),設(shè)計(jì)如下:
用戶:user
角色:role
用戶-角色:user_role
資源:resource(包括上級(jí)菜單、子菜單、按鈕等資源)
角色-資源:role_resource
標(biāo)準(zhǔn)的權(quán)限管理系統(tǒng)設(shè)計(jì)為以上5張表。
注:用戶、用戶-角色我就不做說明了,這兩個(gè)是很簡(jiǎn)單的兩塊,用戶的crud,以及為用戶分配角色(多對(duì)多的關(guān)系)稍微琢磨一下就清楚了,下面都是針對(duì)為角色分配權(quán)限的實(shí)現(xiàn)
后臺(tái)實(shí)現(xiàn)
展示層采用ztree樹
role.jsp
<%@ page contentType="text/html;charset=UTF-8"%> <%@ include file="/views/back/include/taglib.jsp"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta name="decorator" content="back" /> <script type="text/javaScript"> //打開菜單窗口 function openMenuDialog(){ var selected = $("#list").datagrid('getSelected'); if (selected != null) { $("#id").val(selected.id); queryMenus(selected.id); $("#menuWindow").window("open"); } else { $.messager.alert('提示', "未選擇數(shù)據(jù)!"); } } //角色-菜單信息入庫(kù) function ajaxSubmit(rid,idstr){ $.post("${ctx}/roleMenu/save.jhtml",{"roleId":rid,"ids":idstr},function(obj){ $.messager.alert('提示',obj.msg); $("#menuWindow").window('close'); },'json'); } </script> <!-- ztree --> <script type="text/javascript"> var tree = ""; var setting = { check : { chkboxType:{"Y":"ps","N":"s"},//勾選checkbox對(duì)于父子節(jié)點(diǎn)的關(guān)聯(lián)關(guān)系,取消勾選時(shí)不關(guān)聯(lián)父 chkStyle:"checkbox", enable : true //是否復(fù)選框 }, //數(shù)據(jù) data : { simpleData : { enable : true } } }; //查詢菜單信息 function queryMenus(roleId){ $.post('${ctx}/role/treedata.jhtml', {'roleId':roleId}, function(zNodes) { for (var i = 0; i < zNodes.length; i++) { if (zNodes[i].isParent) { } else { //zNodes[i].icon = "${ctxStatic}/images/532.ico";//設(shè)置圖標(biāo) } } tree = $.fn.zTree.init($("#tree"), setting, zNodes); tree.expandAll(true);//全部展開 //var nodes = treeObj.getNodes(); }, 'json'); } //獲取選中節(jié)點(diǎn) function onCheck(){ var rid = $("#id").val(); var treeObj=$.fn.zTree.getZTreeObj("tree"); var nodes=treeObj.getCheckedNodes(true); var ids = new Array(); for(var i=0;i<nodes.length;i++){ //獲取選中節(jié)點(diǎn)的值 ids.push(nodes[i].id); // v+=nodes[i].id + ","; //alert(nodes[i].id); } ajaxSubmit(rid,ids); } </script> </head> <body> <!-- 數(shù)據(jù)表格 --> <table id="list" url='${ctx}/role/list/page.jhtml' method='post' class="easyui-datagrid" style="width:100%;" fitcolumns="true" toolbar='#tb' pagination='true' rownumbers='true' singleSelect='true'> <thead> <tr> <th field='name' sortable='true' width='100'>角色名稱</th> <th field='description' width='200' align='right'>描述</th> <th field='createTimeFormat' width='150' align='center'>創(chuàng)建時(shí)間</th> </tr> </thead> </table> <!-- 編輯欄 --> <div id="tb" style="padding:5px 5px;"> <div> <p2p:permission module="role" code="add"><a href="#" class="easyui-linkbutton" iconCls="icon-add" onclick="openCreateDialog();">新增</a></p2p:permission> <p2p:permission module="role" code="edit"><a href="#" class="easyui-linkbutton" iconCls="icon-edit" onclick="openUpdateDialog();">編輯</a></p2p:permission> <p2p:permission module="role" code="delete"><a href="#" class="easyui-linkbutton" iconCls="icon-remove" onclick="del();">刪除</a></p2p:permission> <p2p:permission module="role" code="authority"><a href="#" class="easyui-linkbutton" iconCls="icon-edit" onclick="openMenuDialog();">設(shè)置權(quán)限</a></p2p:permission> </div> <!-- 搜索項(xiàng) --> <div style="margin-top:5px;padding-left:5px"> 用戶名: <input id="query_name" class="easyui-textbox" type="text" style="width:110px" /> 創(chuàng)建日期: <input id="query_startDate" class="easyui-datebox" style="width:110px"> 至: <input id="query_endDate" class="easyui-datebox" style="width:110px"> <a onclick="reload();" href="#" class="easyui-linkbutton" iconCls="icon-search">查詢</a> </div> </div> <!-- 權(quán)限窗口 --> <div id="menuWindow" class="easyui-window" title="配置權(quán)限" data-options="modal:true,iconCls:'icon-save',footer:'#menuWindowfooter'" style="width:350px;height:420px;padding:10px"> <div id="tree" class="ztree" style="padding: 10px 20px;"></div> </div> <div id="menuWindowfooter" style="padding:5px;text-align:right;"> <a href="#" onclick="onCheck();" class="easyui-linkbutton" data-options="iconCls:'icon-save'">提交</a> </div> </body> </html>
action層
RoleAction.java
@RequestMapping(value = "/treedata.jhtml") @ResponseBody public String treedata(HttpServletRequest request, Model model) { DynamicParams params = new DynamicParams(request); List<Map<String, Object>> mapList = Lists.newArrayList(); params.put("allMenu", "allMenu"); List<Menu> list = authManager.findMenuList(params); List<RoleMenu> roleMenus = authManager.findRoleMenuList(params); for (int i = 0; i < list.size(); i++) { Menu e = list.get(i); Map<String, Object> map = Maps.newHashMap(); map.put("id", e.getId()); map.put("pId", e.getParentId() != null ? e.getParentId() : 0); map.put("name", e.getName()); for (RoleMenu roleMenu : roleMenus) { if (roleMenu.getMenuId() == e.getId()) { map.put("checked", true); } } mapList.add(map); } return toJson(mapList); }
service層
AuthManager.java
// 菜單管理 public List<Menu> findMenuList(DynamicParams params) { List<Menu> menus = new ArrayList<Menu>(); if ("allMenu".equals(params.getString("allMenu"))) { menus = menuDao.findList(params); } else { // 通過用戶查詢角色 List<UserRole> userRoles = userRoleDao.findList(params); // 通過角色查詢菜單 List<RoleMenu> roleMenus = new ArrayList<RoleMenu>(); if (userRoles != null && userRoles.size() > 0) { for (UserRole userRole : userRoles) { params = new DynamicParams(); if (userRole != null) { if (userRole.getRoleId().equals(params.getString("rid"))) { break; } params.put("roleId", userRole.getRoleId().toString()); List<RoleMenu> rms = roleMenuDao.findList(params); for (RoleMenu roleMenu : rms) { roleMenus.add(roleMenu); } } } } // 查詢菜單信息 for (RoleMenu roleMenu : roleMenus) { if (roleMenu != null) { Menu menu = menuDao.find(roleMenu.getMenuId()); if (menu != null) { menus.add(menu); } } } menus = removeDuplicate(menus); Collections.sort(menus); } return menus; }
/** * 去除菜單中重復(fù)項(xiàng) * * @param list * @return */ private List<Menu> removeDuplicate(List<Menu> list) { List<Menu> result = new ArrayList<Menu>(); Set<Long> menuIds = new HashSet<Long>(); for (int i = 0; i < list.size(); i++) { Menu m = list.get(i); if (m != null && menuIds.add(m.getId())) { result.add(m); } } return result; }
public List<RoleMenu> findRoleMenuList(DynamicParams params) { List<RoleMenu> roleMenus = roleMenuDao.findList(params); return roleMenus; }
Dao層
menuDao
@Override protected void createQuery(DynamicParams params, StringBuffer sql, List<Object> args) { sql.append("select s.* from sys_menu s where 1=1 "); String parentId = params.getString("parentId"); if (StringUtils.isNotBlank(parentId)) { sql.append(" and parent_id = ? "); args.add(parentId); } String sort = params.getString("sort"); String order = params.getString("order"); if (StringUtils.isNotBlank(sort)) { sql.append(" order by ").append(hump2underline(sort)); if (StringUtils.isNotBlank(order)) { sql.append(" " + order); } else { sql.append(" desc "); } } else { sql.append("order by sort asc,id desc "); } }
userRoleDao
@Override protected void createQuery(DynamicParams params, StringBuffer sql, List<Object> args) { sql.append("select s.* from sys_user_role s where 1=1 "); Long adminId = params.getLong("adminId"); if (adminId != null) { sql.append(" and s.user_id = ?"); args.add(adminId); } }
roleMenuDao
@Override protected void createQuery(DynamicParams params, StringBuffer sql, List<Object> args) { sql.append("select s.* from ").append("sys_role_menu").append(" s where 1=1 "); Long adminId = params.getLong("roleId"); if (adminId != null) { sql.append(" and s.role_id = ?"); args.add(adminId); } }
在WEB-INF目錄下建立文件夾tlds 建立自定義標(biāo)簽文件shiros.tld,我們通過自定義標(biāo)簽實(shí)現(xiàn)頁(yè)面按鈕的控制。
<span style="color:#333333;"><?xml version="1.0" encoding="UTF-8" ?> <taglib xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd" version="2.0"> <description>p2p permission taglib</description> <display-name>permission taglib</display-name> <tlib-version>1.0</tlib-version> <short-name>p2p_back</short-name> <uri>http://vanfon.p2p.cn/</uri> <tag> <description>權(quán)限校驗(yàn)標(biāo)簽,有權(quán)限就顯示標(biāo)簽體的內(nèi)容,否則不顯示</description> <name>permission</name> <tag-class>com.vanfon.p2p.back.tag.PermissionTag</tag-class> <body-content>JSP</body-content> <attribute> <description></description> <name>module</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> <attribute> <description></description> <name>code</name> <required>true</required> <rtexprvalue>false</rtexprvalue> </attribute> </tag> </taglib></span>
自定義標(biāo)簽類
package com.vanfon.p2p.back.tag; import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import com.vanfon.p2p.entity.system.Admin; import com.vanfon.p2p.entity.system.Menu; import com.vanfon.p2p.manager.system.AuthManager; import com.vanfon.p2p.utils.DynamicParams; import com.vanfon.p2p.utils.SpringContextHolder; /** * 權(quán)限控制標(biāo)簽 * * @author zhangwx * @date 2015-2-5 */ public class PermissionTag extends TagSupport { /** * */ private static final long serialVersionUID = 4592227792811389132L; private String module;// 屬性名必須與JSP自定義標(biāo)簽的屬性名一樣 private String code; public String getModule() { return module; } public void setModule(String module) { this.module = module; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } @Override public int doStartTag() throws JspException { boolean result = false; HttpServletRequest request = (HttpServletRequest) this.pageContext.getRequest();// 通過成員變量獲取HttpServletRequest對(duì)象 Admin admin = (Admin) request.getSession().getAttribute("admin");// 獲取登錄到系統(tǒng)的用戶 if (admin != null) { if ("1".equals(String.valueOf(admin.getIfsuper()))) {// 超級(jí)管理員 result = true; } else { DynamicParams params = new DynamicParams(); params.put("id", String.valueOf(admin.getId())); params.put("module", this.module); params.put("code", this.code); AuthManager authManager = SpringContextHolder.getBean(AuthManager.class); List<Menu> userRoleAuths = authManager.findUserRoleAuthList(params); if (userRoleAuths != null && userRoleAuths.size() > 0) { result = true; } } } return result ? EVAL_BODY_INCLUDE : SKIP_BODY; } }
以上就是該權(quán)限管理中權(quán)限樹的大體實(shí)現(xiàn),完成了java web實(shí)現(xiàn)用戶權(quán)限管理的功能,希望對(duì)大家的學(xué)習(xí)有所幫助。
相關(guān)文章
SpringBoot與Quartz集成實(shí)現(xiàn)分布式定時(shí)任務(wù)集群的代碼實(shí)例
今天小編就為大家分享一篇關(guān)于SpringBoot與Quartz集成實(shí)現(xiàn)分布式定時(shí)任務(wù)集群的代碼實(shí)例,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-03-03Java常用鎖synchronized和ReentrantLock的區(qū)別
這篇文章主要介紹了Java常用鎖synchronized和ReentrantLock的區(qū)別,二者的功效都是相同的,但又有很多不同點(diǎn),下面我們就進(jìn)入文章了解具體的相關(guān)內(nèi)容吧。需要的小伙伴也可以參考一下2022-05-05java數(shù)組排序示例(冒泡排序、快速排序、希爾排序、選擇排序)
java中在運(yùn)用數(shù)組進(jìn)行排序功能時(shí),一般有四種方法:快速排序法、冒泡法、選擇排序法、插入排序法(希爾排序(Shell Sort)是插入排序的一種),下面是一些示例,需要的朋友可以參考下2014-03-03詳解SpringBoot如何優(yōu)雅的進(jìn)行全局異常處理
在SpringBoot的開發(fā)中,為了提高程序運(yùn)行的魯棒性,我們經(jīng)常需要對(duì)各種程序異常進(jìn)行處理,但是如果在每個(gè)出異常的地方進(jìn)行單獨(dú)處理的話,這會(huì)引入大量業(yè)務(wù)不相關(guān)的異常處理代碼,這篇文章帶大家了解一下如何優(yōu)雅的進(jìn)行全局異常處理2023-07-07java 定義長(zhǎng)度為0的數(shù)組/空數(shù)組案例
這篇文章主要介紹了java 定義長(zhǎng)度為0的數(shù)組/空數(shù)組案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03SpringBoot整合SpringSecurity實(shí)現(xiàn)權(quán)限控制之實(shí)現(xiàn)多標(biāo)簽頁(yè)
這篇文章主要介紹了SpringBoot整合SpringSecurity實(shí)現(xiàn)權(quán)限控制之實(shí)現(xiàn)多標(biāo)簽頁(yè),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-11-11