概述
在学习后台的权限控制,自己参考了各种资料后的新手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
展示效果页:
实现代码如下:
<%@ 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
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
/**
* 跳转到分配权限页
* @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 菜单实例
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
/**
* 确认登录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";
}
}
前台页面展示
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,我们通过自定义标签实现页面按钮的控制。
<?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>
自定义标签类
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中配置权限类引用路径
<jsp-config>
<taglib>
<taglib-uri>/adminPower</taglib-uri>
<taglib-location>/WEB-INF/tlds/shiros.tld</taglib-location>
</taglib>
</jsp-config>
页面头部直接引入
<%@ taglib uri="/adminPower" prefix="pr" %>
在页面需要展示的地方包裹标签<.pr : permission code=”2”>
<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所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复