java web實現(xiàn)用戶權(quán)限管理
最近在做一個網(wǎng)站類型項目,主要負責(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)文章
Spring Boot @Scheduled定時任務(wù)代碼實例解析
這篇文章主要介紹了Spring Boot @Scheduled定時任務(wù)代碼實例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
深入淺析Java Object Serialization與 Hadoop 序列化
序列化是指將結(jié)構(gòu)化對象轉(zhuǎn)化為字節(jié)流以便在網(wǎng)絡(luò)上傳輸或者寫到磁盤永久存儲的過程。下面通過本文給大家分享Java Object Serialization與 Hadoop 序列化,需要的朋友可以參考下2017-06-06
SpringBoot+Quartz實現(xiàn)動態(tài)定時任務(wù)
這篇文章主要為大家詳細介紹了springBoot+Quartz實現(xiàn)動態(tài)定時任務(wù),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-09-09
FuncGPT慧函數(shù)保護數(shù)據(jù)安全提高代碼質(zhì)量減少軟件故障(java示例)
這篇文章主要為大家介紹了FuncGPT慧函數(shù)保護數(shù)據(jù)安全提高代碼質(zhì)量減少軟件故障(java示例),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10
SpringBoot實現(xiàn)全局異常的封裝和統(tǒng)一處理
在Spring Boot應(yīng)用中,全局異常的處理是一個非常重要的方面,本文主要為大家詳細介紹了如何在Spring Boot中進行全局異常的封裝和統(tǒng)一處理,需要的可以參考下2023-12-12

