我是靠谱客的博主 快乐枫叶,这篇文章主要介绍后台权限管理控制shiro+jsonMenu,现在分享给大家,希望可以做个参考。

在学习后台的权限控制,自己参考了各种资料后的新手demo,ui框架选型为大家可以参照网上的,项目架构为spring mvc + spring+mybatis,简单易用好上手!搭建好框架后开始了第一个任务,设计并实现一套简单的权限管理功能。

一套最基本的权限管理包括用户、角色、资源。

数据库设计:

资源表:tb_menu (含菜单项、菜单栏、按钮等)
角色表:tb_role(这里我没有创建中间表,所有的权限通过组合的字符串存储)
用户表:tb_users(关联角色ID获取资源权限)

:1)、做法支持1对多,也就是用户有多对多权限控制,表的数据机构设计就靠大家自己构思啦,也可以参考我设计思路
2)、因是简单的DEMO版本,所以service层和controller层写在一起,大家实际做的时候,可不要模仿哦。

后台分发权限页面效果实现
采用ztree树来展示效果
所需JS资源下载路径:http://download.csdn.net/detail/u014799292/9502805

展示效果页:
这里写图片描述

实现代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head lang="en"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>权限功能</title> <link rel="stylesheet" href="${pageContext.request.contextPath}/js/ztree/zTreeStyle/demo.css" type="text/css"> <link rel="stylesheet" href="${pageContext.request.contextPath}/js/ztree/zTreeStyle/zTreeStyle.css" type="text/css"> <script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-1.11.3.min.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/ztree/jquery-migrate-1.2.1.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/ztree/jquery.ztree.core-3.5.js"></script> <script type="text/javascript" src="${pageContext.request.contextPath}/js/ztree/jquery.ztree.excheck-3.5.js"></script> </head> <body> <div class="form" align="center"> <form id="rolePowerForm" action="${pageContext.request.contextPath}/role/powerRole"> <input type="hidden" name="roleId" value="${role.roleId}"/> <input type="hidden" id="menuLinksId" name="menuLinksId" value="${role.menuLinksId}"/> <ul id="treeDemo" class="ztree"></ul><br> <!-- <input id="sumbitBut" type='button' value='确认'/> --> </form> </div> <script> $.browser={}; var zNodes = ${requestScope.roleMenuJsons} // console.log(zNodes); $(function(){ $.browser.msie=false; $.browser.version=0; if(navigator.userAgent.match(/MSIE ([0-9]+)./)){ $.browser.msie=true; $.browser.version=RegExp.$1; } $.fn.zTree.init($("#treeDemo"), setting, zNodes); }); var tree = ""; var setting = { check : { chkboxType:{"Y":"ps","N":"ps"},//勾选checkbox对于父子节点的关联关系,取消勾选时不关联父 chkStyle:"checkbox", enable : true //是否复选框 }, //数据 data : { simpleData : { enable : true, idKey: "id", pIdKey: "pid" } }, callback:{ onCheck:onCheck } }; //获取选中节点 function onCheck(){ var treeObj=$.fn.zTree.getZTreeObj("treeDemo"); var nodes=treeObj.getCheckedNodes(true); var linkIds = ""; for(var i=0;i<nodes.length;i++){ linkIds += nodes[i].id+","; } var list = linkIds.substring(0,linkIds.length-1); $("#menuLinksId").val(list); } </script> </body> </html>

ztree的方法调用可参照API:zTree v3.5.23 API 文档

实体层 RoleMenuJson

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package com.softAngel.admin.beans; /** * 角色授权列表菜单选项 * @author Administrator * */ public class RoleMenuJson { /** */ private Integer id; /** 统一权限节点 */ private Integer pid; /** 功能名称 */ private String name; /** 选中状态 */ private boolean checked; /** 展开状态 */ private boolean open; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Integer getPid() { return pid; } public void setPid(Integer pid) { this.pid = pid; } public String getName() { return name; } public void setName(String name) { this.name = name; } public boolean isChecked() { return checked; } public void setChecked(boolean checked) { this.checked = checked; } public boolean isOpen() { return open; } public void setOpen(boolean open) { this.open = open; } }

Action层

RolePermission

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/** * 跳转到分配权限页 * @param res * @param id */ @RequestMapping(value="/rePowerRole") public String rePowerRole(){ @SuppressWarnings("unchecked") Map<String, Object> map = ReqToMap.toMap(request); String roleId = (String) map.get("roleId"); SqlSession dao = getDao(); Tbrole role = dao.selectOne("role.findTbRoleById",roleId); request.setAttribute("role", role); request.setAttribute("roleMenuJsons", JSONObject.toJSONString(getRoleMenuJsons(dao,role.getMenuLinksId()))); return "/admin/role/rolePower"; } /** * 获取所有资源,并打开拥有的资源权限 * @param dao * @param link * @return */ public static List<RoleMenuJson> getRoleMenuJsons(SqlSession dao,String link){ String []linkTemps = null; if(!StringUtil.isEmpty(link)){ linkTemps = link.split(","); } List<RoleMenuJson> roleMenuJsons = new ArrayList<RoleMenuJson>(); RoleMenuJson titleJson = new RoleMenuJson(); titleJson.setId(0); titleJson.setPid(0); if(!StringUtil.isEmpty(link)){ //如果角色有权限,总目录应该选中 titleJson.setChecked(true); }else{ titleJson.setChecked(false); } List<TbmenuLink> menuList = dao.selectList("menuLink.menuForRoleList"); //获取所有显示的菜单项 for(int i = 0 ; i < menuList.size() ; i ++ ){ TbmenuLink menu = menuList.get(i); RoleMenuJson single = new RoleMenuJson(); //创建节点 single.setId(menu.getMenuId()); single.setPid(menu.getParentId()); single.setName(menu.getMenuName()); if(linkTemps != null){ for(String temp : linkTemps){ if(!StringUtil.isEmpty(temp)){ int number = Integer.parseInt(temp); if(number == menu.getMenuId()){ //拥有的权限功能点将被选中 single.setChecked(true); single.setOpen(true); } } } } roleMenuJsons.add(single); } titleJson.setName("权限菜单"); titleJson.setOpen(true); roleMenuJsons.add(titleJson);//存放头部菜单 return roleMenuJsons; } /** * 分配权限 * @param res * @param id */ @RequestMapping(value="/powerRole") public void powerRole(HttpServletResponse res, @RequestParam(required=true)int roleId){ JSONObject msg = new JSONObject(); if(roleId > 0){ @SuppressWarnings("unchecked") Map<String, Object> map = ReqToMap.toMap(request); SqlSession dao = getDao(); Tbusers loginUser = null; try{ loginUser = (Tbusers) session.getAttribute("loginUser"); map.put("updater",loginUser.getId()); int result = dao.update("role.updateRolePower",map); //更新角色权限 if(result > 0){ msg.put("code", 0); msg.put("info", "授权成功"); }else{ msg.put("code", 1); msg.put("info", "数据有误,授权失败"); } }catch(Exception e){ e.printStackTrace(); logger.info("后台未找到登录用户"); msg.put("code", 1); msg.put("info", "操作失败,后台未找到登录用户"); } }else{ msg.put("code", 1); msg.put("info", "角色信息错误"); } out(msg.toJSONString(), res); }

登录时进行判断操作,获取有JSON权限的菜单栏
Menu 菜单实例

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.softAngel.admin.beans; import java.io.Serializable; import java.util.ArrayList; import java.util.List; /** *@author leopard */ @SuppressWarnings("serial") public class Menu implements Serializable{ /** */ private Integer menuid; /** 栏目名 */ private String menuname; /** 权限类型(所属父级,0本身) */ private Integer menuParentId; /** 链接地址 */ private String url; /** 排序 */ private Integer menuSort; /** 菜单栏图标 */ private String icon; /** 菜单栏集合 */ List<Menu> menus = new ArrayList<Menu>(); public static List<Menu> formatTree(List<Menu> list) { List<Menu> parentNodes = new ArrayList<Menu>();// parentnodes存放所有的父节点 Menu node = new Menu(); for(int i = 0 ; i < list.size() ; i ++){//寻找父级节点 node = list.get(i); if(node.menuParentId == 0){ parentNodes.add(node);//为tree root (父级菜单) } } for(int i = 0 ; i < list.size() ; i ++){//查看菜单栏长度,循环数据 node = list.get(i); for(int j = 0 ; j < parentNodes.size() ; j ++){//循环父节点数据 Menu temp = parentNodes.get(j);//获取父节点 if(node.getMenuParentId() == temp.getMenuid()){//如果子节点的父级ID 和 父级节点的ID相同,归属到对应的父级节点下 temp.getMenus().add(node);//父节点添加对应的子节点ID } } } return parentNodes; } public Integer getMenuid() { return menuid; } public void setMenuid(Integer menuid) { this.menuid = menuid; } public String getMenuname() { return menuname; } public void setMenuname(String menuname) { this.menuname = menuname; } public Integer getMenuParentId() { return menuParentId; } public void setMenuParentId(Integer menuParentId) { this.menuParentId = menuParentId; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public Integer getMenuSort() { return menuSort; } public void setMenuSort(Integer menuSort) { this.menuSort = menuSort; } public String getIcon() { return icon; } public void setIcon(String icon) { this.icon = icon; } public List<Menu> getMenus() { return menus; } public void setMenus(List<Menu> menus) { this.menus = menus; } }

UserAction

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/** * 确认登录POST请求 * @return */ @RequestMapping(method ={RequestMethod.POST},value="/comit") public String comit(HttpServletResponse res, @RequestParam(required=true) String pass, @RequestParam(required=true) String user, final ModelMap model){ Object obj=session.getAttribute("loginUser"); String message=""; if(obj==null){ logger.debug("************ pass="+pass+", user="+user); @SuppressWarnings("rawtypes") Map map=ReqToMap.toMap(request); map.put("loginName",user); map.put("md5pass",MD5Crypter.encryptHEX(pass)); SqlSession dao=getDao(); Tbusers admin = dao.selectOne("user.checkLogin", map); if(admin==null){ message="账号或密码错误"; model.put("login_text", message); return "/login/login"; }else if(admin.getUserState() == 1){ message="此账号不可用"; model.put("login_text", message); return "/login/login"; }else{ map.put("loginCount", admin.getLoginCount()+1); map.put("id", admin.getId()); dao.update("user.updateLogin", map); session.setAttribute("loginUser",admin); /*** 查询有权限的菜单栏列表 ***/ Map<String, Object> param = new HashMap<String, Object>(); List<TbmenuLink> menuLinks = null; if(admin.getUserType()==1){ menuLinks = dao.selectList("power.menuLinks",param); }else if(admin.getUserType()==0){ String rolePower = getRolePowerList(dao,admin.getRoleId()); if(!StringUtil.isEmpty(rolePower)){ param.put("rolePower", rolePower); menuLinks = dao.selectList("power.menuLinks",param);//获取所有菜单栏和菜单项,除按钮外 } } List<Menu> menuTemp = new ArrayList<Menu>(); if(menuLinks != null){ for(int i = 0 ;i<menuLinks.size();i++){ Menu menu = new Menu(); menu.setMenuid(menuLinks.get(i).getMenuId()); menu.setMenuname(menuLinks.get(i).getMenuName()); menu.setMenuParentId(menuLinks.get(i).getParentId()); menu.setUrl(request.getContextPath()+menuLinks.get(i).getMenuUrl()); // System.out.println(request.getContextPath());//项目根路径 if(menuLinks.get(i).getMenuNodeType()==0){//父级菜单 menu.setIcon("icon-sys"); }else{//二级菜单 menu.setIcon("icon-nav"); } menuTemp.add(menu); } } List<Menu> menus = Menu.formatTree(menuTemp); session.setAttribute("menus", JSONObject.toJSONString(menus)); return "/login/main"; } }else{ return "/login/main"; } }

前台页面展示

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
JS展示。。JsonMENU var json = ${sessionScope.menus}; var _menus ={"menus":json}; 旧式原先数据展示: var _menus = {"menus":[ {"menuid":"1","icon":"icon-sys","menuname":"用户管理", "menus":[ {"menuid":"11","menuname":"用户列表1","icon":"icon-nav", "url":"${pageContext.request.contextPath}/user/toUserList"}, ] } ] };

以上可实现获取有权限的菜单项,后台权限角色分配就略过,直接上效果图
这里写图片描述

权限分配好后,用权限用户登录,只能看到有权限的一栏菜单栏和对应的权限菜单项

这里写图片描述

对于按钮,下面以shiro来讲解如何设置按钮权限

页面展示的按钮由shiro权限标签控制

WEB-INF目录下建立文件夹tlds 建立自定义标签文件shiros.tld,我们通过自定义标签实现页面按钮的控制。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?xml version="1.0" encoding="UTF-8"?> <taglib version="2.0" 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 web-jsptaglibrary_2_0.xsd"> <!-- 描述 --> <description>p2p permission taglib</description> <display-name>permission taglib</display-name> <!-- 版本号 --> <tlib-version>1.0</tlib-version> <!-- 标签短名 --> <short-name>admin</short-name> <uri>http://servenboy.cn/</uri> <!--不是必须--> <tag> <description>权限校验标签,有权限就显示标签体的内容,否则不显示</description> <!-- 描述 --> <name>permission</name> <tag-class>com.softAngel.admin.beans.PermissionTag</tag-class> <body-content>JSP</body-content> <!--这里如果设为empty,则无body--> <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>

自定义标签类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package com.softAngel.admin.beans; import javax.servlet.http.HttpSession; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import org.apache.ibatis.session.SqlSession; import com.softAngel.admin.db.StaticFactory; import com.softAngel.admin.web.action.user.UserAction; public class PermissionTag extends TagSupport{ public static final ThreadLocal<SqlSession> localDAO =new ThreadLocal<SqlSession>(); private String module; private String code; @Override public int doStartTag() throws JspException { boolean result = false; HttpSession session = pageContext.getSession(); //CusPermission.getSessionUser() Tbusers user = (Tbusers) session.getAttribute("loginUser"); if(user!=null ){ if(user.getLoginName().equals("admin")){ result = true; }else{ String roleMenuLinkList = UserAction.getRolePowerList(getDao(), user.getRoleId()); if(roleMenuLinkList!=null){ String LinkIds[] = roleMenuLinkList.split(","); for(String temp : LinkIds){ if(temp.equals(code)){ result = true; break; } } } } } // 真:返回EVAL_BODY_INCLUDE(执行标签);假:返回SKIP_BODY(跳过标签不执行) return result ? EVAL_BODY_INCLUDE : SKIP_BODY; } 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; } protected SqlSession getDao(){ SqlSession dao=localDAO.get(); if(dao==null){ dao=StaticFactory.getSqlSession(true); localDAO.set(dao); } return dao; } }

在web.xml中配置权限类引用路径

复制代码
1
2
3
4
5
6
<jsp-config> <taglib> <taglib-uri>/adminPower</taglib-uri> <taglib-location>/WEB-INF/tlds/shiros.tld</taglib-location> </taglib> </jsp-config>

页面头部直接引入

复制代码
1
<%@ taglib uri="/adminPower" prefix="pr" %>

在页面需要展示的地方包裹标签<.pr : permission code=”2”>

复制代码
1
2
3
4
5
<div class="btnList"> <pr:permission module="1" code="2"><input type="button" value='测试1-1'/></pr:permission> <pr:permission module="1" code="3"><input type="button" value='测试1-2'/></pr:permission> <pr:permission module="1" code="4"><input type="button" value='测试1-3'/></pr:permission> </div>

以上就是该权限管理中权限树(为角色分配权限)的大体实现。

简单详解:<.pr : permission module=”1” code=”2”> 中的module 代表 资源ID为1的 角色管理菜单栏 (也就是所谓的父级) code代表资源ID 为2的 按钮(父级菜单下对应的子级菜单栏项或按钮),也可理解为权限资源里面同时含有 1,2这两个ID的权限,按钮-测试1-1 就会显示出来,否则为隐藏不可见

最后

以上就是快乐枫叶最近收集整理的关于后台权限管理控制shiro+jsonMenu的全部内容,更多相关后台权限管理控制shiro+jsonMenu内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部