权限系统_权限系统设计 - CSDN
精华内容
参与话题
  • 权限系统的设计

    万次阅读 2019-08-04 20:08:44
    权限系统设计 前言 权限管理是所有后台系统的都会涉及的一个重要组成部分,主要目的是对不同的人访问资源进行权限的控制,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,隐私数据泄露等问题。 目前在...

    可能是史上最全的权限系统设计

    权限系统设计

    前言

    权限管理是所有后台系统的都会涉及的一个重要组成部分,主要目的是对不同的人访问资源进行权限的控制,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,隐私数据泄露等问题。

    目前在公司负责权限这块,所以对权限这块的设计比较熟悉,公司采用微服务架构,权限系统自然就独立出来了,其他业务系统包括商品中心,订单中心,用户中心,仓库系统,小程序,多个APP等十几个系统和终端

    1.权限模型

    迄今为止最为普及的权限设计模型是RBAC模型,基于角色的访问控制(Role-Based Access Control)

    1.1 RBAC0模型

    RBAC0模型如下:

    这是权限最基础也是最核心的模型,它包括用户/角色/权限,其中用户和角色是多对多的关系,角色和权限也是多对多的关系。

    用户是发起操作的主体,按类型分可分为2B和2C用户,可以是后台管理系统的用户,可以是OA系统的内部员工,也可以是面向C端的用户,比如阿里云的用户。

    角色起到了桥梁的作用,连接了用户和权限的关系,每个角色可以关联多个权限,同时一个用户关联多个角色,那么这个用户就有了多个角色的多个权限。有人会问了为什么用户不直接关联权限呢?在用户基数小的系统,比如20个人的小系统,管理员可以直接把用户和权限关联,工作量并不大,选择一个用户勾选下需要的权限就完事了。但是在实际企业系统中,用户基数比较大,其中很多人的权限都是一样的,就是个普通访问权限,如果管理员给100人甚至更多授权,工作量巨大。这就引入了"角色(Role)"概念,一个角色可以与多个用户关联,管理员只需要把该角色赋予用户,那么用户就有了该角色下的所有权限,这样设计既提升了效率,也有很大的拓展性。

    权限是用户可以访问的资源,包括页面权限,操作权限,数据权限:

    • 页面权限: 即用户登录系统可以看到的页面,由菜单来控制,菜单包括一级菜单和二级菜单,只要用户有一级和二级菜单的权限,那么用户就可以访问页面
    • 操作权限: 即页面的功能按钮,包括查看,新增,修改,删除,审核等,用户点击删除按钮时,后台会校验用户角色下的所有权限是否包含该删除权限,如果是,就可以进行下一步操作,反之提示无权限。有的系统要求"可见即可操作",意思是如果页面上能够看到操作按钮,那么用户就可以操作,要实现此需求,这里就需要前端来配合,前端开发把用户的权限信息缓存,在页面判断用户是否包含此权限,如果有,就显示该按钮,如果没有,就隐藏该按钮。某种程度上提升了用户体验,但是在实际场景可自行选择是否需要这样做
    • 数据权限: 数据权限就是用户在同一页面看到的数据是不同的,比如财务部只能看到其部门下的用户数据,采购部只看采购部的数据,在一些大型的公司,全国有很多城市和分公司,比如杭州用户登录系统只能看到杭州的数据,上海用户只能看到上海的数据,解决方案一般是把数据和具体的组织架构关联起来,举个例子,再给用户授权的时候,用户选择某个角色同时绑定组织如财务部或者合肥分公司,那么该用户就有了该角色下财务部或合肥分公司下的的数据权限。

    以上是RBAC的核心设计及模型分析,此模型也叫做RBAC0,而基于核心概念之上,RBAC还提供了扩展模式。包括RBAC1,RBAC2,RBAC3模型。下面介绍这三种类型

    1.2 RBAC1模型

    此模型引入了角色继承(Hierarchical Role)概念,即角色具有上下级的关系,角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构,实现角色间的单继承。这种设计可以给角色分组和分层,一定程度简化了权限管理工作。

    1.3 RBAC2模型

    基于核心模型的基础上,进行了角色的约束控制,RBAC2模型中添加了责任分离关系,其规定了权限被赋予角色时,或角色被赋予用户时,以及当用户在某一时刻激活一个角色时所应遵循的强制性规则。责任分离包括静态责任分离和动态责任分离。主要包括以下约束:

    • 互斥角色: 同一用户只能分配到一组互斥角色集合中至多一个角色,支持责任分离的原则。互斥角色是指各自权限互相制约的两个角色。比如财务部有会计和审核员两个角色,他们是互斥角色,那么用户不能同时拥有这两个角色,体现了职责分离原则
    • 基数约束: 一个角色被分配的用户数量受限;一个用户可拥有的角色数目受限;同样一个角色对应的访问权限数目也应受限,以控制高级权限在系统中的分配
    • 先决条件角色: 即用户想获得某上级角色,必须先获得其下一级的角色

    1.4 RBAC3模型

    即最全面的权限管理,它是基于RBAC0,将RBAC1和RBAC2进行了整合

    1.5 用户组

    当平台用户基数增大,角色类型增多时,而且有一部分人具有相同的属性,比如财务部的所有员工,如果直接给用户分配角色,管理员的工作量就会很大,如果把相同属性的用户归类到某用户组,那么管理员直接给用户组分配角色,用户组里的每个用户即可拥有该角色,以后其他用户加入用户组后,即可自动获取用户组的所有角色,退出用户组,同时也撤销了用户组下的角色,无须管理员手动管理角色。
    根据用户组是否有上下级关系,可以分为有上下级的用户组和普通用户组:

    • 具有上下级关系的用户组: 最典型的例子就是部门和职位,可能多数人没有把部门职位和用户组关联起来吧。当然用户组是可以拓展的,部门和职位常用于内部的管理系统,如果是面向C端的系统,比如淘宝网的商家,商家自身也有一套组织架构,比如采购部,销售部,客服部,后勤部等,有些人拥有客服权限,有些人拥有上架权限等等,所以用户组是可以拓展的
    • 普通用户组: 即没有上下级关系,和组织架构,职位都没有关系,也就是说可以跨部门,跨职位,举个例子,某电商后台管理系统,有拼团活动管理角色,我们可以设置一个拼团用户组,该组可以包括研发部的后台开发人员,运营部的运营人员,采购部的人员等等。

    每个公司都会涉及到到组织和职位,下面就重点介绍这两个。

    1.5.1 组织

    常见的组织架构如下图:

    我们可以把组织与角色进行关联,用户加入组织后,就会自动获得该组织的全部角色,无须管理员手动授予,大大减少工作量,同时用户在调岗时,只需调整组织,角色即可批量调整。组织的另外一个作用是控制数据权限,把角色关联到组织,那么该角色只能看到该组织下的数据权限。

    1.5.2 职位

    假设财务部的职位如下图:

    每个组织部门下都会有多个职位,比如财务部有总监,会计,出纳等职位,虽然都在同一部门,但是每个职位的权限是不同的,职位高的拥有更多的权限。总监拥有所有权限,会计和出纳拥有部分权限。特殊情况下,一个人可能身兼多职。

    1.6 含有组织/职位/用户组的模型

    根据以上场景,新的权限模型就可以设计出来了,如下图:

    根据系统的复杂度不同,其中的多对多关系和一对一关系可能会有变化,

    • 在单系统且用户类型单一的情况下,用户和组织是一对一关系,组织和职位是一对多关系,用户和职位是一对一关系,组织和角色是一对一关系,职位和角色是一对一关系,用户和用户组是多对对关系,用户组和角色是一对一关系,当然这些关系也可以根据具体业务进行调整。模型设计并不是死的,如果小系统不需要用户组,这块是可以去掉的。
    • 分布式系统且用户类型单一的情况下,到这里权限系统就会变得很复杂,这里就要引入了一个"系统"概念,此时系统架构是个分布式系统,权限系统独立出来,负责所有的系统的权限控制,其他业务系统比如商品中心,订单中心,用户中心,每个系统都有自己的角色和权限,那么权限系统就可以配置其他系统的角色和权限。
    • 分布式系统且用户类型多个的情况下,比如淘宝网,它的用户类型包括内部用户,商家,普通用户,内部用户登录多个后台管理系统,商家登录商家中心,这些做权限控制,如果你作为架构师,该如何来设计呢?大神可以在评论区留言交流哦!

    2.授权流程

    授权即给用户授予角色,按流程可分为手动授权和审批授权。权限中心可同时配置这两种,可提高授权的灵活性。

    • 手动授权: 管理员登录权限中心为用户授权,根据在哪个页面授权分为两种方式:给用户添加角色,给角色添加用户。给用户添加角色就是在用户管理页面,点击某个用户去授予角色,可以一次为用户添加多个角色;给角色添加用户就是在角色管理页面,点击某个角色,选择多个用户,实现了给批量用户授予角色的目的。
    • 审批授权: 即用户申请某个职位角色,那么用户通过OA流程申请该角色,然后由上级审批,该用户即可拥有该角色,不需要系统管理员手动授予。

    3.表结构

    有了上述的权限模型,设计表结构就不难了,下面是多系统下的表结构,简单设计下,主要提供思路:

    4.权限框架

    • Apache Shrio
    • Spring Security

    在项目中可以采用其中一种框架,它们的优缺点以及如何使用会在后面的文章中详细介绍.

    5.结语

    权限系统可以说是整个系统中最基础,同时也可以很复杂的,在实际项目中,会遇到多个系统,多个用户类型,多个使用场景,这就需要具体问题具体分析,但最核心的RBAC模型是不变的,我们可以在其基础上进行扩展来满足需求。

    最后,如果您觉得这篇文章对您有帮助,可以点个赞,谢谢支持!

    展开全文
  • 用户权限管理系统

    万次阅读 2018-07-19 15:57:44
    该项目主要是完成用户权限系统的开发,该系统分为登陆、用户管理、角色管理和菜单管理4个模块。 分别在登陆模块实现了简单的登陆功能;用户管理模块实现了用户的增加、删除、修改、查看信息、用户角色分配等功能;...

    该项目主要是完成用户权限系统的开发,该系统分为登陆、用户管理、角色管理和菜单管理4个模块。
    分别在登陆模块实现了简单的登陆功能;用户管理模块实现了用户的增加、删除、修改、查看信息、用户角色分配等功能;角色管理模块实现了角色的新增、修改和删除,对应角色的权限查看,重新给各个角色分配功能等功能;菜单管理模块实现了菜单的增删改功能。
    本项目结构上分为表现层、业务层和数据访问层。层次间的依赖关系自下到上。采用的技术有三层架构、Jquery 等。其中表现层采用easyui框架开发;业务层封装业务流程,为适应业务的变更,每一业务模块均有专门的接口及实现类,数据访问层封装数据,为适应数据的变更,每个模块均有专门的接口及实现类。

    1功能一

    1.1、功能名称

    系统登录功能

    1.2、客户端界面及描述

    登陆界面如图1所示。

    图1登陆界面

    登录按钮功能描述:

    1. 判断用户名密码是否输入 是:继续,否:return;
    2. 获取用户名密码,使用ajax提交服务器端C#进行验证,并返回验证结果;
    3. 客户端通过ajax回调函数获取服务端的验证结果,成功:页面跳转Main.aspx; 否则提示登录失败信息。

    1.3、客户端主要核心脚本

    <script>

            $(function () {

                $('#btnOK').click(function () {

                    var usercode = $('#usercode').val();

                    var pwd = $('#pwd').val();

                    $.ajax({

                        type: 'post',

                        url: "Login.aspx?action=login",

                        data: { usercode: usercode, pwd: pwd },

                        //contentType: 'application/json',

                        dataType: 'json',

                        success: function (data) {

                            if (data.isSuccessed) {

                                location.href = "Main.aspx";

                            }

                            else

                                alert(data.Message);

                        },

                        error: function (xmlReq, err, c) {

                            alert("error:" + err);

                        }

                    });

                })

            })

        </script>

    1.4、服务器端代码

    private void CheckLogin()

        {

            string usercode = Request["usercode"];

            string pwd = Request["pwd"];

            SYSTEM.BLL.sysuser bll = new SYSTEM.BLL.sysuser();

            var user = bll.GetModel(usercode);

            if (user != null)

            {

                if (user.pwd == pwd)

                {

                    Session["username"] =user.username.ToString();  //记录当前用户在session 里面

                    WriteMessage(true, "登陆成功");

                }

                else

                {

                    WriteMessage(false, "登陆失败");

                }

            }

            else

            {

                WriteMessage(false, "登陆失败");

            }

        }

    2功能二

    2.1、功能名称

    用户管理功能

    2.2、客户端界面及描述

    用户管理主界面如图2所示,增加用户如图3所示,修改用户如图4所示,用户角色分配如图5所示。

    图2用户管理主界面

    用户管理主界面描述:点击左边系统设置的用户管理按钮,进入主界面,查看所有用户信息。

    图3新增用户

    新增用户功能描述:点击右边界面的新增按钮,弹出新增数据界面,对用户进行增加操作。点击弹出窗口中的确定,即可增加成功;如果点击关闭,即可取消添加。

    图4修改用户

    修改用户功能描述:点击右边界面的修改按钮,弹出修改数据界面,对用户进行修改操作。点击弹出窗口中的确定,即可修改成功;如果点击关闭,即可取消修改。

    图5用户角色分配

    用户角色分配功能描述:点击右边界面的用户角色按钮,弹出角色数据界面,对用户进行角色分配操作。点击弹出窗口中的确定,即可完成角色分配;如果点击关闭,即可取消分配。

    2.3、客户端主要核心脚本

    2.3.1用户管理主界面

      function loaddata() {

                    $("#dg").datagrid({

                        url: "userlist.aspx?action=select",//加载的URL  

                        isField: "usercode",

                        pagination: true,//显示分页  

                        pageSize: 5,//分页大小  

                        pageList: [5, 10, 15, 20],//每页的个数  

                        fit: true,//自动补全  

                        fitColumns: true,

                        toolbar: '#tb',

                        sortName: 'usercode',

                        queryParams: {},//condition(),

                        singleSelect: true,

                        //iconCls: "icon-save",//图标  

                        //title: "用户管理",

                        columns: [[      //每个列具体内容  

                                  { field: 'usercode', title: '用户名', width: 100, sortable: true },

                                  { field: 'username', title: '姓名', width: 100, sortable: true },

                                  {

                                      field: 'pwd', title: '密码', width: 100,

                                      formatter: function (value, row, index) {

                                          return '******';

                                      }

                                  },

                                  { field: 'cmt', title: '备注' }

                        ]]

                    })

                }

    2.3.1增加用户

       $('#btnAdd').click(function () {

                    $('#w').dialog({

                        title: '新增数据',

                        width: 400,

                        height: 200,

                        closed: false,

                        cache: false,

                        href: 'useredit.aspx',

                        modal: true,

                        buttons: [{

                            text: '确定',

                            iconCls: 'icon-ok',

                            handler: function () {

                                //数据保存代码                            

                                $('#ff').form('submit', {

                                    url: "useredit.aspx?action=addrecord",    //表单提交地址 并带参数

                                    onSubmit: function () {

                                        return $(this).form('validate');  //验证表单是否通过验证规则

                                    },

                                    success: function (returndata) {

                                        var obj = eval("(" + returndata + ")")

                                        if (obj.isSuccessed) {

                                            $('#dg').datagrid('reload');   //刷新数据表格datagrid

                                            $('#w').dialog('close');    //关闭弹出新增窗口

                                            $.messager.show({

                                                title: '提示',

                                                msg: obj.Message,

                                                timeout: 2000,

                                                showType: 'show'

                                            });

                                        }

                                        else {

                                            alert('保存失败!');

                                        }

                                    }

                                });

                            }

                        }, {

                            text: '关闭',

                            iconCls: 'icon-delete',

                            handler: function () {

                                $('#w').dialog('close');                     //关闭弹出新增窗口

                            }

                        }]

                    });

                });

    2.3.1修改用户

      $('#btnEdit').click(function () {

                    var row = $('#dg').datagrid('getSelected');

                    if (row == null) {

                        $.messager.show({

                            title: '提示',

                            msg: '请选择您要编辑的数据.',

                            timeout: 2000,

                            showType: 'slide'

                        });

                        return;

                    }

     

                    $('#w').dialog({

                        title: '修改数据',

                        width: 400,

                        height: 200,

                        closed: false,

                        cache: false,

                        href: 'useredit.aspx?action=update&id=' + row.usercode,

                        modal: true,

                        buttons: [{

                            text: '确定',

                            iconCls: 'icon-ok',

                            handler: function () {

                                //数据保存代码                            

                                $('#ff').form('submit', {

                                    url: "useredit.aspx?action=updaterecord&id=" + row.usercode,    //表单提交地址 并带参数

                                    onSubmit: function () {

                                        return $(this).form('validate');  //验证表单是否通过验证规则

                                    },

                                    success: function (returndata) {

                                        var obj = eval("(" + returndata + ")")

                                        if (obj.isSuccessed) {

                                            $('#dg').datagrid('reload');   //刷新数据表格datagrid

                                            $('#w').dialog('close');    //关闭弹出新增窗口

                                            $.messager.show({

                                                title: '提示',

                                                msg: obj.Message,

                                                timeout: 2000,

                                                showType: 'show'

                                            });

                                        }

                                        else {

                                            alert('保存失败!');

                                        }

                                    }

                                });

                            }

                        }, {

                            text: '关闭',

                            iconCls: 'icon-delete',

                            handler: function () {

                                $('#w').dialog('close');                     //关闭弹出新增窗口

                            }

                        }]

                    });

                });

    2.3.1删除用户

        $('#btnDel').click(function () {

                    var row = $('#dg').datagrid('getSelected');

                    if (row == null) {

                        $.messager.show({

                            title: '提示',

                            msg: '请选择您要删除的数据.',

                            timeout: 2000,

                            showType: 'slide'

                        });

                        return;

                    }

                    $.ajax({

                        url: 'useredit.aspx?action=delete&id=' + row.usercode,

                        success: function (data) {

                          

                            if (data.isSuccessed) {

                                $('#dg').datagrid('reload');   //刷新数据表格datagrid

     

                                $.messager.show({

                                    title: '提示',

                                    msg: data.Message,

                                    timeout: 2000,

                                    showType: 'show'

                                });

                            }

                            else {

                                alert('删除失败!');

                            }

                        }

     

                    })

     

                });

    2.3.1用户角色分配

      $('#btnrole').click(function () {

                    var row = $('#dg').datagrid('getSelected');

                    if (row == null) {

                        $.messager.show({

                            title: '提示',

                            msg: '请选择您要分配角色的用户.',

                            timeout: 2000,

                            showType: 'slide'

                        });

                        return;

                    }

                    $('#w').dialog({

                        title: '角色数据',

                        width: 400,

                        height: 200,

                        closed: false,

                        cache: false,

                        href: 'userrolelist.aspx?action=choose&id=' + row.usercode,

                        modal: true,

                        buttons: [{

                            text: '确定',

                            iconCls: 'icon-ok',

                            handler: function () {

                                var rolerow = $('#dgrole').datagrid('getSelected');

     

                                $.ajax({

                                    type: "GET",

                                    url: "userrolelist.aspx?action=save",                                    data: { usercode: row.usercode, roleid: rolerow.roleid },

                                                                  success: function (returndata) {

                                        var obj = eval("(" + returndata + ")");

                                        if (obj.isSuccessed) {

                                            $('#w').dialog('close');

                                        }

                                        else { }

                                    }

                                });

                            }

                        }, {

                            text: '关闭',

                            iconCls: 'icon-delete',

                            handler: function () {

                                $('#w').dialog('close');                     //关闭弹出新增窗口

                            }

                        }]

                    });

                });

    2.4、服务器端代码

      private void GetList()

        {

                int pageindex = int.Parse(Request.Form["page"]);

                int pagesize = int.Parse(Request.Form["rows"]);

                string sort = Request.Form["sort"];

                string order = Request.Form["order"];

                string value = Request.Form["value"];

                SYSTEM.BLL.sysuser bll = new SYSTEM.BLL.sysuser();

                DataTable dt = new DataTable();

                ResultData data = new ResultData();

                string strOrder = "";

                if(!string.IsNullOrEmpty(sort))

                {

                    strOrder = sort + " " + order;

                }

                string strWhere = "";

                if (!string.IsNullOrEmpty(value))

                {

                    strWhere = string.Format(" usercode like '%{0}%' or username like '%{0}%'", value);

                }

                data.total = bll.GetRecordCount(strWhere);

                data.rows = bll.GetListByPage(strWhere, strOrder, (pageindex - 1) * pagesize + 1, pageindex * pagesize).Tables[0];

                WriteData(Newtonsoft.Json.JsonConvert.SerializeObject(data));

            }      

     private void Save()

        {     

            model.usercode = Request.Form["usercode"];

            model.username = Request.Form["username"];

            model.cmt = Request.Form["cmt"];

            model.pwd = Request.Form["pwd"];

            if (blluser.Add(model))

            {

                WriteMessage(true, "添加成功");

            }

            else

            {

                WriteMessage(false, "添加失败");

            }      

        }

        private void GetOne()

        {

            SYSTEM.Model.sysuser model = blluser.GetModel(Request["id"].ToString());

     

            WriteData(Newtonsoft.Json.JsonConvert.SerializeObject(model));       

        }

        private void Update()

        {

            //新建对象

            SYSTEM.Model.sysuser model = blluser.GetModel(Request["id"].ToString());       

            model.username = Request.Form["username"].ToString();

            model.cmt = Request.Form["cmt"].ToString();

            if (blluser.Update(model))

            {

                WriteMessage(true, "修改成功!");   //响应,向前端传送数据

            }

            else

            {

                WriteMessage(false, "修改失败!");

            }       

        }

        private void Delete()

        {

            if (blluser.Delete(Request["id"].ToString()))

            {

                WriteMessage(true, "删除成功!");   //响应,向前端传送数据

            }

            else

            {

                WriteMessage(false, "删除失败!");

            }

        }

    3功能三

    3.1、功能名称

    角色管理功能

    3.2、客户端界面及描述

    角色权限查看如图6所示,角色权限保存如图7所示。

    图6角色权限查看

    角色权限查看功能描述:点击查看,即可查看各个角色的对应权限。

    图7角色权限保存

    角色权限保存功能描述:先选择一个角色,再在功能中选择功能,点击保存。再点击查看,即可添加角色对应的功能。

    3.3、客户端主要核心脚本

     function loadtreedata() {

                $('#tg').treegrid({

                    title: '系统功能列表',

                    fit: true,

                    animate: true,//是否用动画效果

                    collapsible: false,//是否可折叠

                    //pagination: true,//分页控件

                    rownumbers: true,//行号

                    //fitColumns: true,

                    url: 'rolelist.aspx?action=menuselect',

                    method: 'get',

                    toolbar: '#menutb',

                    idField: 'id',//根据那个字段判断树节点关系

                    treeField: 'funname',//根据那个列展现树

                    showFooter: false,//是否使用页脚

                    sortName: 'funid',//默认排序字段,后台通过参数名“sort”获取

     

                    singleSelect: false,

                    //sortOrder: 'desc',//默认排序规则,后台通过参数名“order”获取

                    columns: [[

                        { title: '', field: 'funid', hidden: true },

                        { title: '功能', field: 'funname', width: 220, sortable: true },

                        { title: '地址', field: 'url', width: 150, sortable: true },

                        { title: '图标', field: 'icno', width: 80 },

                        { title: '备注', field: 'cmt', width: 100, sortable: true }

     

                    ]],

                    onBeforeExpand: function (node) {

                    },

                    onLoadSuccess: function () {

                    },

                    onClickRow: function (node) {

                        //点击行触发

                    },

                    onClickCell: function (rowIndex, field, value) {//点击表格触发

                    }

                });

            }

     

     function loaddata() {

                $("#dg").datagrid({

                    url: "rolelist.aspx?action=select",//加载的URL  

                    isField: "roleid",

                    pagination: true,//显示分页  

                    pageSize: 5,//分页大小  

                    pageList: [5, 10, 15, 20],//每页的个数  

                    fit: true,//自动补全  

                    fitColumns: true,

                    toolbar: '#tb',

                    sortName: 'roleid',

                    queryParams: {},//condition(),

                    singleSelect: true,

                    //iconCls: "icon-save",//图标  

                    //title: "用户管理",

                    columns: [[      //每个列具体内容  

                              { field: 'roleid', title: '', hidden: true },

                              { field: 'rolename', title: '角色名称', width: 200, sortable: true },

     

                              { field: 'cmt', title: '备注', width: 500 },

                              {

                                  field: 'right', title: '权限',

                                  formatter: function (value, row, index) {

                                      return '<a href="#" οnclick="ShowMenu(' + row.roleid + ')">查看</a>';

                                  }

                              },

                    ]]

                })

            }

      $('#btnSaveMenu').on('click', function () {

                    var row = $('#dg').datagrid('getSelected');

                    if (row == null) {

                        $.messager.show({

                            title: '提示',

                            msg: '请选择你要分配功能的角色.',

                            timeout: 2000,

                            showType: 'slide'

                        });

                        return;

                    }

     

                    var newfunids = [];

                    var rows = $('#tg').treegrid('getSelections');

                    for (i = 0 ; i < rows.length; i++) {

                        newfunids.push(rows[i].id);

                    }

     

                    $.ajax({

                        url: 'rolelist.aspx?action=savemenu&id=' + row.roleid,

                        type: 'post',

                        data: JSON.stringify(newfunids),

                        success: function (data) {

                            var obj = eval("(" + data + ")")

                            if (obj.isSuccessed) {

                                $('#tg').datagrid('reload');   //刷新数据表格datagrid

     

                                $.messager.show({

                                    title: '提示',

                                    msg: obj.Message,

                                    timeout: 2000,

                                    showType: 'show'

                                });

                            }

                            else {

                                alert('保存失败!');

                            }

                        }

     

                    })

     

                });

    3.4、服务器端代码

      private void SaveMenu()

            {

                SYSTEM.BLL.sysrolefun bll = new SYSTEM.BLL.sysrolefun();

                string id = Request["id"].ToString();

                foreach(var m in  bll.GetModelList(string.Format(" roleid = {0}", id)))

                {

                    bll.Delete(m.id);

                }

     

                string[] strarr = HttpUtility.UrlDecode(Request.Form.ToString()).Replace("]", "").Replace("[", "").Split(',');

     

                foreach(var funid in strarr)

                {

                    var mm = new SYSTEM.Model.sysrolefun();

                    mm.funid = decimal.Parse(funid);

                    mm.roleid = decimal.Parse(id);

                    bll.Add(mm);

                }

     

                WriteMessage(true, "OK!");

     

               

            }

    4功能

    4.1、功能名称

    菜单管理功能

    4.2、客户端界面及描述

    菜单管理主界面如图8所示,新增菜单如图9所示,修改菜单如图10所示。

     

    图8菜单管理主界面

    菜单管理主界面描述:点击左边的菜单管理按钮,打开如上图所示的界面。对菜单的相关信息进行管理。

    图9增加菜单

    增加菜单功能描述:点击页面的新增按钮,弹出新增数据界面,对需要的菜单进行添加。点击确定,即可完成添加;点击关闭,添加取消。

    图10修改菜单

    修改菜单功能描述:点击页面的修改按钮,弹出修改数据界面,对需要的菜单进行修改。点击确定,即可完成修改;点击关闭,修改取消。

    4.3、客户端主要核心脚本

    function loaddata() {

                $('#tg').treegrid({

                    title: '',

                    fit: true,

                    animate: true,//是否用动画效果

                    collapsible: false,//是否可折叠

                    //pagination: true,//分页控件

                    rownumbers: true,//行号

                    //fitColumns: true,

                    url: 'menulist.aspx?action=select',

                    method: 'get',

                    toolbar: '#tb',

                    idField: 'id',//根据那个字段判断树节点关系

                    treeField: 'funname',//根据那个列展现树

                    showFooter: false,//是否使用页脚

                    sortName: 'funid',//默认排序字段,后台通过参数名“sort”获取

                    //sortOrder: 'desc',//默认排序规则,后台通过参数名“order”获取

                    columns: [[

                        { title: '功能', field: 'funname', width: 220, sortable: true },

                        { title: '地址', field: 'url', width: 150, sortable: true },

                        { title: '图标', field: 'icno', width: 80 },

                        { title: '备注', field: 'cmt', width: 100, sortable: true }

     

                    ]],

                    onBeforeExpand: function (node) {

                    },

                    onLoadSuccess: function () {

                    },

                    onClickRow: function (node) {

                        //点击行触发

                    },

                    onClickCell: function (rowIndex, field, value) {//点击表格触发

                    }

                });

            }

    <script>

            //获取当前窗口的操作类型

            var action = '<% =action%>';

            var id = '<% =id%>';

            $(function () {

                loadform();  //如果是编辑进入,需要加载编辑数据

                $('#pid').combobox({

                    url:'menuedit.aspx?action=combobox',

                    valueField:'funid',

                    textField:'funname'

                });

                //$('#cc').combotree({

                //    url: 'get_data.php',

                //    required: true

                //});

            })

     

            function loadform() {

                if (action == 'update') {

                    $.ajax({

                        url: 'menuedit.aspx?action=getrecord&id=' + id,

                        success: function (data) {

                            data = eval('(' + data + ')');

                            $('#ff').form('load', data);

                        }

     

                    })

                }

            }

        </script>

     

    4.4、服务器端代码

      private void GetTreeList()

            {

                SYSTEM.BLL.sysfunction bll = new SYSTEM.BLL.sysfunction();

                DataTable dt = new DataTable();

                ResultData data = new ResultData();

              

     

                data.total = bll.GetRecordCount("");

                data.rows = bll.GetTreeList("").Tables[0];

                WriteData(Newtonsoft.Json.JsonConvert.SerializeObject(data));

            }

     

    展开全文
  • 如何设计网站权限系统?

    千次阅读 2018-06-06 11:35:11
    第1章 权限管理原理知识 1.1 什么是权限管理 1.2 用户认证 1.2.1 概念 1.2.1 用户认证流程 1.2.2 关键对象 1.3 用户授权 1.3.1 概念 1.3.2 授权流程 1.3.3 关键对象 1.3.4 分配权限 1.3.5 权限模型 1.3.5 权限控制...

    第1章 权限管理原理知识

    1.1 什么是权限管理

    只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户访问而且只能访问自己被授权的资源
    权限管理包括用户认证和授权两部分。

    1.2 用户认证

    1.2.1 概念

    用户认证:用户去访问系统,系统要验证用户身份的合法性。最常用的用户身份验证的方法:
    - 用户密码登录
    - 指纹打卡机
    - 基于证书验证方法

    系统验证用户身份合法,用户方可访问系统的资源

    1.2.1 用户认证流程

    用户认证流程

    1.2.2 关键对象
    • subject: 主体,理解为用户,可能是程序,都要去访问系统的资源,系统需要对subject进行身份认证。
    • principal: 身份信息,通常是唯一的,一个主体还有多个身份信息,但是都有一个主身份信息(parimary principal)。
    • credential: 凭证信息,可以是密码、证书、指纹。

    总结: 主体在进行身份认证时需要提供身份信息和凭证信息。

    1.3 用户授权

    1.3.1 概念

    用户授权,简单理解为访问控制,在用户认证通过后,系统对用户访问资源进行控制,用户具有资源的访问权限方可访问。

    1.3.2 授权流程

    图中橙色为授权流程

    1.3.3 关键对象

    授权的过程理解为: who 对 what 进行how操作。

    • who: 主体即subject,subject在认证通过后系统进行访问控制。
    • what: 资源(Resource),subject 必须就别资源的访问权限才可访问该资源。比如:系统用户列表页面、商品修改菜单、商品id为001的商品信息。
    • how: 权限/许可(permission),针对资源的权限或许可,subject具有permission访问资源,如何访问/操作需要定义permission,权限比如:用户添加、用户修改、商品删除。
    1.3.4 分配权限

    用户需要分配相应的权限才可访问相应的资源。权限是对于资源的操作许可。
    通常给用户分配资源权限需要将权限信息持久化,比如存储在关系数据库里。
    把用户信息、权限管理、用户分配的权限信息写到数据库中。

    1.3.5 权限模型
    • 主体(账号、密码)
    • 资源(资源名称、访问地址)
    • 权限 (权限名称、资源id)
    • 角色 (角色名称)
    • 角色和权限关系(角色id、权限id)
    • 主体和角色关系 (主体id、角色id)

    如下图:
    这里写图片描述

    通常企业开发中将资源和权限表合并为一张权限表,如下:
    - 资源(资源名称,访问地址)
    - 权限(权限名称、资源id)

    合并为
    - 权限(权限名称、资源名称、资源访问地址)

    这里写图片描述
    上图常被称为权限管理的通用模型,不过企业开发中根据系统自身的特点还会对上图进行修改,但是用户、角色、权限、用户角色关系、角色权限关系是需要去理解的。

    1.3.6 权限控制(授权核心)
    1.3.6.1 基于角色的访问控制

    RBAC(Role Based Access Control),基于角色的访问控制
    比如:
    系统角色包括:部门经理、总经理…(角色是针对用户划分的)
    系统代码实现

    //如果该用户是部门经理则可以访问if中的代码
    if(user.hasRole('部门经理')){
       //系统资源的内容
       //用户报表查看
    }

    问题:
    角色是针对人划分的,人作为用户在系统中是属于活动的内容,如果说该角色可以访问的资源出现变更,需要修改你的代码。
    比如:部门经理和总经理都可以查看进行报表的查看,代码改为:

    if(user.hasRole('部门经理')||user.hasRole('总经理')){
       //系统资源的内容
       //用户报表查看
    }

    基于角色的访问控制是不利于系统维护的。

    1.3.6.2 基于资源的访问控制

    RBAC(Resource Based Access Control),基于资源的访问控制
    资源在系统中是不变的,比如资源有:类中的方法,页面中的按钮。
    对资源的范文需要具有permission权限,代码可以写为;

    if(user.hasPermission('用户报表查看')){
       //系统资源的内容
       //用户报表查看
    }

    上边的方法可以解决用户角色变更不用修改上边权限控制的代码。
    如果需要变更权限只需要在分配权限模块去操作,给部门经理或总经理增或删除权限。
    建议使用基于资源的访问控制实现权限管理。

    第2章 权限管理解决方案

    2.1 什么是粗粒度和细粒度权限

    粗粒度权限管理,对资源类型的权限管理。资源类型比如:菜单、URL连接、用户添加页面、用户信息、类方法、页面中的按钮。
    粗粒度权限管理比如:超级管理员可以访问用户添加 页面、用户信息等全部页面。
    部门管理员可以访问用户信息页面包括页面中的所有按钮
    细粒度权限管理,对资源实例的权限管理。资源实例就是资源类型的具体化,比如:用户id为001的修改连接,1110班的用户信息、行政部的员工。
    细粒度权限管理就是数据级别的权限管理
           细粒度权限管理比如: 部门经理只可以访问本部门的员工信息,用户只可以看到自己的菜单,大区经理只能查看本辖区的销售订单。

    2.2 如何实现粗粒度和细粒度权限管理

    如何实现粗粒度权限管理?
           粗粒度权限管理比较容易将权限管理的代码抽取出来在系统架构级别统一处理。比如:通过springmvc拦截器实现授权。
    如何实现细粒度权限管理?
    建议细粒度权限管理在业务层去控制。
    比如:部门经理只查询本部门员工信息,在service接口提供一个部门id的查询,controller中根据当前用户的信息得到该用户属于哪个部门,调用service时将部门id传入service,实现用户只查询本部门的员工。

    2.3 基于url拦截方式实现

    基于url拦截的方式实现在实际开发中比较常用的一种方式。
    对于web系统,通过filter过滤器实现url拦截,也可以springmvc的拦截器实现基于 url的拦截

    2.4 使用权限管理框架实现

    对于粗粒度权限管理,建立使用优秀权限管理框架来实现,节省开发时间,提高开发效率,shiro就是一个优秀权限管理框架。

    第3章.基于url的权限管理

    3.1 基于url权限管理流程

    这里写图片描述

    3.2 搭建环境

    3.2.1 数据库

    需要创建:用户表、角色表、权限表、用户角色表、角色权限表

    CREATE TABLE `sys_user` (
      `id` varchar(36) NOT NULL COMMENT '主键',
      `usercode` varchar(32) NOT NULL COMMENT '账号',
      `username` varchar(64) NOT NULL COMMENT '姓名',
      `password` varchar(32) NOT NULL COMMENT '密码',
      `salt` varchar(64) DEFAULT NULL COMMENT '盐',
      `locked` char(1) DEFAULT NULL COMMENT '账号是否锁定,1:锁定,0未锁定',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `sys_role` (
      `id` varchar(36) NOT NULL,
      `name` varchar(128) NOT NULL,
      `available` char(1) DEFAULT NULL COMMENT '是否可用,1:可用,0不可用',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `sys_user_role` (
      `id` varchar(36) NOT NULL,
      `sys_user_id` varchar(32) NOT NULL,
      `sys_role_id` varchar(32) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `sys_permission` (
      `id` bigint(20) NOT NULL COMMENT '主键',
      `name` varchar(128) NOT NULL COMMENT '资源名称',
      `type` varchar(32) NOT NULL COMMENT '资源类型:menu,button,',
      `url` varchar(128) DEFAULT NULL COMMENT '访问url地址',
      `percode` varchar(128) DEFAULT NULL COMMENT '权限代码字符串',
      `parentid` bigint(20) DEFAULT NULL COMMENT '父结点id',
      `parentids` varchar(128) DEFAULT NULL COMMENT '父结点id列表串',
      `sortstring` varchar(128) DEFAULT NULL COMMENT '排序号',
      `available` char(1) DEFAULT NULL COMMENT '是否可用,1:可用,0不可用',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    CREATE TABLE `sys_role_permission` (
      `id` varchar(36) NOT NULL,
      `sys_role_id` varchar(32) NOT NULL COMMENT '角色id',
      `sys_permission_id` varchar(32) NOT NULL COMMENT '权限id',
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    
    

    insert  into `sys_permission`(`id`,`name`,`type`,`url`,`percode`,`parentid`,`parentids`,`sortstring`,`available`) values (1,'权限','','',NULL,0,'0/','0','1'),(11,'商品管理','menu','/item/queryItem.action',NULL,1,'0/1/','1.','1'),(12,'商品新增','permission','/item/add.action','item:create',11,'0/1/11/','','1'),(13,'商品修改','permission','/item/editItem.action','item:update',11,'0/1/11/','','1'),(14,'商品删除','permission','','item:delete',11,'0/1/11/','','1'),(15,'商品查询','permission','/item/queryItem.action','item:query',11,'0/1/15/',NULL,'1'),(21,'用户管理','menu','/user/query.action','user:query',1,'0/1/','2.','1'),(22,'用户新增','permission','','user:create',21,'0/1/21/','','1'),(23,'用户修改','permission','','user:update',21,'0/1/21/','','1'),(24,'用户删除','permission','','user:delete',21,'0/1/21/','','1');
    
    /*Data for the table `sys_role` */
    
    insert  into `sys_role`(`id`,`name`,`available`) values ('ebc8a441-c6f9-11e4-b137-0adc305c3f28','商品管理员','1'),('ebc9d647-c6f9-11e4-b137-0adc305c3f28','用户管理员','1');
    
    /*Data for the table `sys_role_permission` */
    
    insert  into `sys_role_permission`(`id`,`sys_role_id`,`sys_permission_id`) values ('ebc8a441-c6f9-11e4-b137-0adc305c3f21','ebc8a441-c6f9-11e4-b137-0adc305c','12'),('ebc8a441-c6f9-11e4-b137-0adc305c3f22','ebc8a441-c6f9-11e4-b137-0adc305c','11'),('ebc8a441-c6f9-11e4-b137-0adc305c3f24','ebc9d647-c6f9-11e4-b137-0adc305c','21'),('ebc8a441-c6f9-11e4-b137-0adc305c3f25','ebc8a441-c6f9-11e4-b137-0adc305c','15'),('ebc9d647-c6f9-11e4-b137-0adc305c3f23','ebc9d647-c6f9-11e4-b137-0adc305c','22'),('ebc9d647-c6f9-11e4-b137-0adc305c3f26','ebc8a441-c6f9-11e4-b137-0adc305c','13');
    
    /*Data for the table `sys_user` */
    
    insert  into `sys_user`(`id`,`usercode`,`username`,`password`,`salt`,`locked`) values ('lisi','lisi','李四','bf07fd8bbc73b6f70b8319f2ebb87483','uiwueylm','0'),('zhangsan','zhangsan','张三','cb571f7bd7a6f73ab004a70322b963d5','eteokues','0');
    
    /*Data for the table `sys_user_role` */
    
    insert  into `sys_user_role`(`id`,`sys_user_id`,`sys_role_id`) values ('ebc8a441-c6f9-11e4-b137-0adc305c3f28','zhangsan','ebc8a441-c6f9-11e4-b137-0adc305c'),('ebc9d647-c6f9-11e4-b137-0adc305c3f28','lisi','ebc9d647-c6f9-11e4-b137-0adc305c');

    3.2.2 技术 架构

    springmvc + mybatis + jquery easyui

    3.2.3 系统登录

    系统登录相当于用户认证,用户登录成功,要在session中记录用户的身份信息。
    操作流程:
    1.用户进入登录页面
    2.输入用户名和密码进行登录
    3.进行用户名和密码校验
    4.如果校验通过,在session中记录用户信息

    3.2.3.1 用户的身份信息
    /**
     * 用户身份信息,存入session 由于tomcat将session会序列化在本地硬盘上,所以使用Serializable接口
     * 
     */
    public class ActiveUser implements java.io.Serializable {
        private String userid;//用户id(主键)
        private String usercode;// 用户账号
        private String username;// 用户名称
    
        private List<SysPermission> menus;// 菜单
        private List<SysPermission> permissions;// 权限
    
        // set get方法省略
    }
    
    3.2.3.1 mapper

    使用逆向工程生成的mapper,根据用户账户查询用户(sys_user)信息。

    3.2.3.2 service

    接口功能:根据用户的身份和密码 进行认证,如果认证通过,返回用户身份信息
    认证过程:
    - 根据用户身份(账号)查询数据库,如果查询不到用户不存在
    - 对输入的密码 和数据库密码 进行比对,如果一致,认证通过

    @Override
        public ActiveUser authenticat(String userCode, String password)
                throws Exception {
            /**
                    认证过程:
                     根据用户身份(账号)查询数据库,如果查询不到用户不存在
                     对输入的密码 和数据库密码 进行比对,如果一致,认证通过
             */
            //根据用户账号查询数据库
            SysUser sysUser = this.findSysUserByUserCode(userCode);
    
            if(sysUser == null){
                //抛出异常
                throw new CustomException("用户账号不存在");
            }
    
            //数据库密码 (md5密码 )
            String password_db = sysUser.getPassword();
    
            //对输入的密码 和数据库密码 进行比对,如果一致,认证通过
            //对页面输入的密码 进行md5加密 
            String password_input_md5 = new MD5().getMD5ofStr(password);
            if(!password_input_md5.equalsIgnoreCase(password_db)){
                //抛出异常
                throw new CustomException("用户名或密码 错误");
            }
            //得到用户id
            String userid = sysUser.getId();
            //根据用户id查询菜单 
            List<SysPermission> menus =this.findMenuListByUserId(userid);
    
            //根据用户id查询权限url
            List<SysPermission> permissions = this.findPermissionListByUserId(userid);
    
            //认证通过,返回用户身份信息
            ActiveUser activeUser = new ActiveUser();
            activeUser.setUserid(sysUser.getId());
            activeUser.setUsercode(userCode);
            activeUser.setUsername(sysUser.getUsername());//用户名称
    
            //放入权限范围的菜单和url
            activeUser.setMenus(menus);
            activeUser.setPermissions(permissions);
    
            return activeUser;
        }
    3.2.3.2 controller(记录session)
        public String login(HttpSession session, String randomcode,String usercode,String password)throws Exception{
    
            //校验验证码,防止恶性攻击
            //从session获取正确验证码
            String validateCode = (String) session.getAttribute("validateCode");
    
            //输入的验证和session中的验证进行对比 
            if(!randomcode.equals(validateCode)){
                //抛出异常
                throw new CustomException("验证码输入错误");
            }
    
            //调用service校验用户账号和密码的正确性
            ActiveUser activeUser = sysService.authenticat(usercode, password);
    
            //如果service校验通过,将用户身份记录到session
            session.setAttribute("activeUser", activeUser);
            //重定向到商品查询页面
            return "redirect:/first.action";
        }

    3.2.4 用户认证拦截器

    3.2.4.1 编写认证拦截器
    //用于用户认证校验、用户权限校验
        @Override
        public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception {
    
            //得到请求的url
            String url = request.getRequestURI();
    
            //判断是否是公开 地址
            //实际开发中需要公开 地址配置在配置文件中
            //从配置中取逆名访问url
    
            List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL");
            //遍历公开 地址,如果是公开 地址则放行
            for(String open_url:open_urls){
                if(url.indexOf(open_url)>=0){
                    //如果是公开 地址则放行
                    return true;
                }
            }
    
    
            //判断用户身份在session中是否存在
            HttpSession session = request.getSession();
            ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
            //如果用户身份在session中存在放行
            if(activeUser!=null){
                return true;
            }
            //执行到这里拦截,跳转到登陆页面,用户进行身份认证
            request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
    
            //如果返回false表示拦截不继续执行handler,如果返回true表示放行
            return false;
        }
    
    
    3.2.4.2 配置拦截器
        <!--拦截器 -->
        <mvc:interceptors>
    
            <mvc:interceptor>
                <!-- 用户认证拦截 -->
                <mvc:mapping path="/**" />
                <bean class="cn.ty.ssm.controller.interceptor.LoginInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    

    3.2.5 授权

    3.2.5.1 commonURL.properties

    在此配置文件配置公共访问地址,共用访问地址只要 通过用户认证,不需要对公共访问地址分配 权限即可访问。

    3.2.5.2 获取用户权限范围的菜单

    思路:在用户认证时,认证通过,根据用户id从数据库获取用户权限范围的菜单,将菜单的集合存储在session 中。

    public class ActiveUser implements java.io.Serializable {
        private String userid;//用户id(主键)
        private String usercode;// 用户账号
        private String username;// 用户名称
    
        private List<SysPermission> menus;// 菜单
        private List<SysPermission> permissions;// 权限
    
        // set get方法省略
    }
    

    mapper接口:根据用户id查询用户权限的菜单

     <!-- 根据用户id查询菜单 -->
      <select id="findMenuListByUserId"  parameterType="string" resultType="cn.ty.ssm.po.SysPermission">
            SELECT 
          * 
        FROM
          sys_permission 
        WHERE TYPE = 'menu' 
          AND id IN 
          (SELECT 
            sys_permission_id 
          FROM
            sys_role_permission 
          WHERE sys_role_id IN 
            (SELECT 
              sys_role_id 
            FROM
              sys_user_role 
            WHERE sys_user_id = #{id}))
      </select>

    service接口:根据用户id查询用户权限的菜单

    public List<SysPermission> findMenuListByUserId(String userid)
                throws Exception {
    
            return sysPermissionMapperCustom.findMenuListByUserId(userid);
        }
    3.2.5.3 获取用户权限范围的url

    思路:
    在用户认证时,认证通过,根据用户id从数据库获取权限分为的url,将url的集合存储在session 中。
    mapper接口:根据用户id查询用户权限的url

      <!-- 根据用户id查询url -->
      <select id="findPermissionListByUserId" parameterType="string" resultType="cn.ty.ssm.po.SysPermission">
          SELECT 
          * 
        FROM
          sys_permission 
        WHERE TYPE = 'permission' 
          AND id IN 
          (SELECT 
            sys_permission_id 
          FROM
            sys_role_permission 
          WHERE sys_role_id IN 
            (SELECT 
              sys_role_id 
            FROM
              sys_user_role 
            WHERE sys_user_id = #{id}))
      </select>
    

    service接口:根据用户id查询权限的url

    @Override
    public List<SysPermission> findPermissionListByUserId(String userid)
            throws Exception {
    
        return sysPermissionMapperCustom.findPermissionListByUserId(userid);
    }
    
    3.2.5.4 用户认证通过取出菜单和url放入session
        //得到用户id
            String userid = sysUser.getId();
            //根据用户id查询菜单 
            List<SysPermission> menus =this.findMenuListByUserId(userid);
    
            //根据用户id查询权限url
            List<SysPermission> permissions = this.findPermissionListByUserId(userid);
    
            //认证通过,返回用户身份信息
            ActiveUser activeUser = new ActiveUser();
            activeUser.setUserid(sysUser.getId());
            activeUser.setUsercode(userCode);
            activeUser.setUsername(sysUser.getUsername());//用户名称
    
            //放入权限范围的菜单和url
            activeUser.setMenus(menus);
            activeUser.setPermissions(permissions);
    
    3.2.5.6 菜单动态显示
    
        <c:if test="${activeUser.menus!=null }">
                    <ul>
                    <c:forEach items="${activeUser.menus }" var="menu">
                        <li><div>
                            <a title="${menu.name }" ref="1_1" href="#"
                                rel="${baseurl }/${menu.url }" icon="icon-log"><span
                                class="icon icon-log">&nbsp;</span><span class="nav"><a href=javascript:addTab('${menu.name }','${baseurl }/${menu.url }')>${menu.name }</a></span></a>
                        </div></li>
                    </c:forEach>
                    </ul>
                </c:if>
    3.2.5.7 授权拦截器
    //在执行handler之前来执行的
        //用于用户认证校验、用户权限校验
        @Override
        public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception {
    
            //得到请求的url
            String url = request.getRequestURI();
    
            //判断是否是公开 地址
            //实际开发中需要公开 地址配置在配置文件中
            //从配置中取逆名访问url
    
            List<String> open_urls = ResourcesUtil.gekeyList("anonymousURL");
            //遍历公开 地址,如果是公开 地址则放行
            for(String open_url:open_urls){
                if(url.indexOf(open_url)>=0){
                    //如果是公开 地址则放行
                    return true;
                }
            }
    
            //从配置文件中获取公共访问地址
            List<String> common_urls = ResourcesUtil.gekeyList("commonURL");
            //遍历公用 地址,如果是公用 地址则放行
            for(String common_url:common_urls){
                if(url.indexOf(common_url)>=0){
                    //如果是公开 地址则放行
                    return true;
                }
            }
    
            //获取session
            HttpSession session = request.getSession();
            ActiveUser activeUser = (ActiveUser) session.getAttribute("activeUser");
            //从session中取权限范围的url
            List<SysPermission> permissions = activeUser.getPermissions();
            for(SysPermission sysPermission:permissions){
                //权限的url
                String permission_url = sysPermission.getUrl();
                if(url.indexOf(permission_url)>=0){
                    //如果是权限的url 地址则放行
                    return true;
                }
            }
    
            //执行到这里拦截,跳转到无权访问的提示页面
            request.getRequestDispatcher("/WEB-INF/jsp/refuse.jsp").forward(request, response);
    
            //如果返回false表示拦截不继续执行handler,如果返回true表示放行
            return false;
        }
    
    3.2.5.8 配置授权拦截器
        <!--拦截器 -->
        <mvc:interceptors>
    
            <mvc:interceptor>
                <!-- 用户认证拦截 -->
                <mvc:mapping path="/**" />
                <bean class="cn.ty.ssm.controller.interceptor.LoginInterceptor"></bean>
            </mvc:interceptor>
            <mvc:interceptor>
                <!-- 授权拦截 -->
                <mvc:mapping path="/**" />
                <bean class="cn.ty.ssm.controller.interceptor.PermissionInterceptor"></bean>
            </mvc:interceptor>
        </mvc:interceptors>
    

    总结

    使用基于url拦截的权限管理方式,实现起来比较简单,不依赖于框架,使用Web提供filter就可以实现。
    问题
    需要将所有的url全部配置起来,有些繁琐,不易维护,url(资源)和权限表示方式不规范。

    这里写图片描述
    喜欢的话关注一下,有趣又内涵的文档将第一时间发送。

    展开全文
  • 权限系统---简介

    千次阅读 热门讨论 2014-11-30 19:22:55
    打算写这篇博客开始就在想,为什么要存在权限系统,不开发它不行吗,它的存在能为我们带来什么?   还记得第一次敲“机房收费系统”的时候吗,那个时候有三种用户一般管理员、操作员、管理员。不同的用户看的页面...

    开篇:

            打算写这篇博客开始就在想,为什么要存在权限系统,不开发它不行吗,它的存在能为我们带来什么?

           还记得第一次敲“机房收费系统”的时候吗,那个时候有三种用户一般管理员、操作员、管理员。不同的用户看的页面不同,他们所拥有的操作就不同。这样说来我们在很早以前就开始进行了权限的设置,所以今天为大家讲解权限问题应该是很容易被理解的。

          权限的作用:

                   1是为了让用户各司其职,只要管理好自己的一亩三分地就可以了。

                   2它更是一种安全策略。用户可以访问而且只能访问自己被授权的资源。

     原理

    用户登录后,判断用户是否存在,如果存在查询用户所具有的权限,根据用户的权限做出不同的显示。


    权限系统的具体操作,添加资源即权限后,可以将权限赋值给角色,将这个角色直接赋予了用户,当用户登录的时候,就可以根据角色的权限展示了。这种方式是基于角色的访问控制。而我们这次要做的权限系统时既要基于角色又要基于权限,它的意思是用户可以通过通过中间的角色来获得权限,也可以直接将某项或某几项权限赋给用户。

     现状:

    对于在企业环境中的访问控制方法,一般有三种:

    1.自主型访问控制方法(DAC/授权Authorization)。目前在我国的大多数的信息系统中的访问控制模块中基本是借助于自主型访问控制方法中的访问控制列表(ACLs)。使用自主访问控制机制,一个用户可以自主地说明其资源允许系统中哪些用户以何种权限进行共享。

    2.强制型访问控制方法(多级安全/MultilevelSecurity)。用于多层次安全级别的军事应用。在强制型访问控制方法中,用户和资源都是被赋予了固定的安全属性,在每次访问发生时,检测安全属性以便确定用户是否具有权访问该资源。

    3.基于角色的访问控制方法(RBAC-Role-BasedAccess Control)。是目前公认的解决大型企业的统一资源访问控制的有效方法。其显著的两大特征是:

    (1)减小授权管理的复杂性,降低管理开销。

    (2)灵活地支持企业的安全策略,并对企业的变化有很大的伸缩性。

     概念解释:

    资源:其实就是权限,系统的所有权限信息。权限的资源包括系统、模块、页面和操作。权限具有上下级关系,是一个树状的结构。用户有没有这项操作,用户能不能看到这个页面,用户 能不能具有这个模块。用户所拥有的客体就是资源。这些讲的都是功能权限,还有一种数据权限。

          角色:角色就是一组资源。其实他就是对资源的一次整合,为了满足业务需求,将这些资源整合成各种角色。

          用户:应用系统的具体操作者,用户可以自己拥有权限信息,可以归属于0~n个角色,可属于0~n个组。他的权限集是自身具有的权限、所属的各角色具有的权限、所属的各组具有的权限的合集。它与权限、角色、组之间的关系都是n对n的关系。

          组织:为了更好地管理用户,对用户进行分组归类,简称为用户分组。组也具有上下级关系,可以形成树状视图。组也可以具有自己的角色信息、权限信息。       

          授权:将资源的权限分配给用户,或将角色分配给用户。这样用户就具有权限。

    项目中遇到的问题:

    1功能权限与数据权限不明确:

    在需求分析的初期,大家对目前开发的权限功能实现不够明确,导致了一些理解上的偏差。目前的设计的权限系统是在功能权限的基础之上的,基本没有涉及到数据权限的范围。但是各个系统都是在数据权限才能够达到的高度进行讨论,导致了权限和子系统理解的不一致。讨论过后,明确职责。

    总结:

    一直想找一本关于权限的书看看,但是最后没有找到,只能是通过一些博客和文档来丰富自己关于权限方面的了解。在了解一个知识之前先不要关注与细节,不要关注于它怎么实现的,先跳出了看看,以一个局外之人的身份去审视它,会看到它的全面。

    展开全文
  • 有赞权限系统

    2019-03-28 13:08:20
    文 | 毛成光、马纯洁 on 零售 有赞作为一个商家服务公司,通过产品和服务,帮助互联网时代的生意人成功。在新零售的浪潮下,有赞零售为商家提供不同规模的门店和网店经营解决方案,帮助零售商家们快速进入新零售时代...
  • 权限设计-系统登录用户权限设计

    万次阅读 多人点赞 2018-01-08 09:56:59
    需求分析—场景 ...有如下几个要求: 1. 权限等级不同:公司领导登录后可查看所有员工信息,部门领导登录后只可查看本部门员工的信息,员工...3. 操作权限不同:如系统管理员可以在信息发布界面进行增删改查发布信息
  • 项目中权限控制系统的设计

    万次阅读 2020-04-20 21:51:27
    RCBA 权限:权利(能做的)和限制...最开始真正有权限的概念是在Linux上关于文件和目录的权限,再后来联想到在Windows系统下对某些系统文件的操作,慢慢回想起以前所遇到的关于权限的事情!权限管理,平时里很多地方...
  • 系统权限管理设计

    万次阅读 多人点赞 2014-07-16 12:19:47
    关于权限菜单的设计
  • 完整的权限管理系统

    千次阅读 2018-08-24 16:01:37
    权限管理系统定义 权限管理是一个几乎所有后台系统的都会涉及的一个重要组成部分,主要目的是对整个后台管理系统进行权限的控制,而针对的对象是员工,避免因权限控制缺失或操作不当引发的风险问题,如操作错误,...
  • 7-Zip->解压到"BaiduNetdisk_x.x.x";把解压出来的以$开头的文件夹删掉;移动解压出来的文件夹到目标位置;安装完成。 2.先安装或复制之前的安装;压缩文件夹或复制文件夹到其他路径下;卸载原来安装的;...
  • 如何开启MIUI11系统的root权限

    万次阅读 2019-06-16 00:28:00
    MIUI11系统怎么样拥有了root权限?大伙都知道,安卓系统有root权限,如果手机拥有了root相关权限,能够实现更完美的功能,举个例子,大伙部门的营销部门,使用大多数营销应用都需要在root权限下使用,如果手机没能获...
  • 后台经验分享:如何做权限管理系统设计?

    万次阅读 多人点赞 2017-11-15 14:07:14
    作者:橘子洲头 全文共 2210 字 5 图,阅读需要 6 分钟 ———— / BEGIN / ———— ...在人人都是产品经理的网站上蛰居了4年,学习了四年,由于最近的工作方向偏向于后台,在设计后台时时常会查阅后台的相关...
  • Linux系统下在普通用户如何使用root权限

    万次阅读 多人点赞 2016-05-10 20:09:19
    在Linux系统下,以普通用户身份登录之后,如何使用root用户的root权限
  • 目前,大多数权限系统,都是基于RBAC的理念来设计的,关于RBAC,摘抄一下百度百科的解释: 在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而 得到这些角色的权限。这就极大地简化了权限的管理。在一个...
  • 权限”用英语该用哪个?

    万次阅读 2010-02-08 20:19:00
    权限”是我们设计系统必不可少的,关于“权限”的英语单词也很多,该用哪个呢?我参照有关“权限”的英文软件,总结如下,不足之处,多多指正:Permission:权限,包括动作和客体,比如:添加文档,“添加”是动作...
  • Winform通用框架之权限管理系统

    万次阅读 多人点赞 2019-12-05 16:06:54
    Winfrom通用权限管理系统 Winfrom通用权限管理--登录 Winfrom通用权限管理--菜单 Winfrom通用权限管理系统--数据库设计 Winfrom通用权限管理----数据库问题 心血来潮,想写个通用管理系统整体界面结构采用VS 可...
  • 随时随地阅读更多技术实战干货,获取项目源码、学习资料,请关注源代码社区公众号(ydmsq... apk程序是运行在虚拟机上的,对应的是Android独特的权限机制,只有体现到文件系统上时才使用linux的权限设置。(一)linux...
  • java权限管理与用户角色权限设计

    万次阅读 多人点赞 2018-06-16 00:14:28
    java权限管理与用户角色权限设计2016年10月29日 19:24:41阅读数:12545实现业务系统中的用户权限管理 B/S系统中的权限比C/S中的更显的重要,C/S系统因为具有特殊的客户端,所以访问用户的权限检测可以通过客户端...
  • Android6.0 如何添加更改系统设置权限

    万次阅读 2017-01-14 11:25:41
    但是我在利用框架申请更改系统设置权限时(如更改手机来电铃声需要此权限),一般的框架没有用。因此需要自己手动利用代码去申请,代码如下: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // 判断...
  • 一个基于角色的权限控制系统

    万次阅读 多人点赞 2016-06-24 14:01:19
    基于角色的权限控制也就是说通过角色,来控制用户访问的模块,不同的用户拥有不同的角色,将具有不同的访问权限
1 2 3 4 5 ... 20
收藏数 1,306,521
精华内容 522,608
关键字:

权限系统