后台权限管理控制shiro+jsonMenu

来源:互联网 发布:游族网络是双休么 编辑:程序博客网 时间:2024/05/21 06:16

在学习后台的权限控制,自己参考了各种资料后的新手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展示。。JsonMENUvar 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 就会显示出来,否则为隐藏不可见

0 0
原创粉丝点击