java web實現(xiàn)用戶權(quán)限管理
最近在做一個網(wǎng)站類型項目,主要負(fù)責(zé)后臺,ui框架選型為jquery easy ui,項目架構(gòu)為spring mvc + spring jdbc,簡單易用好上手!搭建好框架后開始了第一個任務(wù),設(shè)計并實現(xiàn)一套簡單的權(quán)限管理功能。
一套最基本的權(quán)限管理包括用戶、角色、資源。
實現(xiàn)效果:
數(shù)據(jù)庫設(shè)計,設(shè)計如下:
用戶:user
角色:role
用戶-角色:user_role
資源:resource(包括上級菜單、子菜單、按鈕等資源)
角色-資源:role_resource
標(biāo)準(zhǔn)的權(quán)限管理系統(tǒng)設(shè)計為以上5張表。
注:用戶、用戶-角色我就不做說明了,這兩個是很簡單的兩塊,用戶的crud,以及為用戶分配角色(多對多的關(guān)系)稍微琢磨一下就清楚了,下面都是針對為角色分配權(quán)限的實現(xiàn)
后臺實現(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ù)!"); } } //角色-菜單信息入庫 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對于父子節(jié)點的關(guān)聯(lián)關(guān)系,取消勾選時不關(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é)點 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é)點的值 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)建時間</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> <!-- 搜索項 --> <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ù)項 * * @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)簽實現(xiàn)頁面按鈕的控制。
<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)限校驗標(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對象 Admin admin = (Admin) request.getSession().getAttribute("admin");// 獲取登錄到系統(tǒng)的用戶 if (admin != null) { if ("1".equals(String.valueOf(admin.getIfsuper()))) {// 超級管理員 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)限樹的大體實現(xiàn),完成了java web實現(xiàn)用戶權(quán)限管理的功能,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
SpringBoot與Quartz集成實現(xiàn)分布式定時任務(wù)集群的代碼實例
今天小編就為大家分享一篇關(guān)于SpringBoot與Quartz集成實現(xiàn)分布式定時任務(wù)集群的代碼實例,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03Java常用鎖synchronized和ReentrantLock的區(qū)別
這篇文章主要介紹了Java常用鎖synchronized和ReentrantLock的區(qū)別,二者的功效都是相同的,但又有很多不同點,下面我們就進(jìn)入文章了解具體的相關(guān)內(nèi)容吧。需要的小伙伴也可以參考一下2022-05-05java數(shù)組排序示例(冒泡排序、快速排序、希爾排序、選擇排序)
java中在運用數(shù)組進(jìn)行排序功能時,一般有四種方法:快速排序法、冒泡法、選擇排序法、插入排序法(希爾排序(Shell Sort)是插入排序的一種),下面是一些示例,需要的朋友可以參考下2014-03-03詳解SpringBoot如何優(yōu)雅的進(jìn)行全局異常處理
在SpringBoot的開發(fā)中,為了提高程序運行的魯棒性,我們經(jīng)常需要對各種程序異常進(jìn)行處理,但是如果在每個出異常的地方進(jìn)行單獨處理的話,這會引入大量業(yè)務(wù)不相關(guān)的異常處理代碼,這篇文章帶大家了解一下如何優(yōu)雅的進(jìn)行全局異常處理2023-07-07java 定義長度為0的數(shù)組/空數(shù)組案例
這篇文章主要介紹了java 定義長度為0的數(shù)組/空數(shù)組案例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03SpringBoot整合SpringSecurity實現(xiàn)權(quán)限控制之實現(xiàn)多標(biāo)簽頁
這篇文章主要介紹了SpringBoot整合SpringSecurity實現(xiàn)權(quán)限控制之實現(xiàn)多標(biāo)簽頁,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-11-11