美文网首页
高级第八天:RBAC

高级第八天:RBAC

作者: w漫漫 | 来源:发表于2020-09-08 08:56 被阅读0次

    RBAC

    主要内容

    1.RBAC的介绍

    2.传统项目数据库设计方案

    3.RBAC设计方案

    4.RBAC的详细版本

    5.URL权限控制

    一.RBAC简介

    [1]RBAC的概念

    基于角色的权限访问控制(Role-Based Access Control)作为传动访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在RBAC中,权限与角色相关连,用户通过称为适当角色的成员而得到这些角色的权限.这就极大的简化了权限的管理rbac:一种数据库设计思想,根据设计数据库设计方案,完成项目的权限控制

    [2]权限的使用情景

    2.1不同用户登录后看到的菜单是不一样的

    2.2不同用户看到的页面效果不一样

    2.2.1有的用户可以看到"授权"按钮,或有的用户可以看见"删除"按钮

    2.3不同用户完成的功能是不一样的

    2.3.1有的用户可以执行删除,有的可以执行新增

    2.4场景示意图

    小公司和比较简单的权限系统使用的基于用户的访问控制如下

    这种访问控制只适用于操作人员比较少的系统,如果操作人员较多,对每个操作人员都进行授权操作,无疑是非常繁琐的.所以我们就需要基于角色的访问控制

    [3]学习RBAC需要掌握的要素

    3.1如何设计数据库中表

    3.2如何根据数据库完成项目

    3.3RBAC核心是角色,在数据库设计时一定有角色

    3.4根据RBAC设计思想,设计出来的方案是非常灵活的

    二.实现技术设计方案

    [1]需求实现方案一

    使用C:if判断的方式进行实现,和中级书写的SXTOA一样,在left中动态的判断该用户下的标签即可

    缺点:

        (1)所有的菜单标签必须提前的书写好.不可以更改

        (2)如果需要添加菜单,只能更改源代码

    [2]需求实现方案二

    数据库结构实现如图所示

    缺点:

    (1)新建一个用户时,在用户表中添加一条数据

    (2)新建一个用户时,在关联表中添加N条数据

    (3)每次新建一个用户需要添加:1+N(关联几个)条数据

    [3]需求实现方案三

    1.基于RBAC的设计方案

    1.1设定好在某些情况下哪些菜单需要被关联

    1.1.1例如:管理员可以看到所有菜单

    1.1.2例如:销售总监可以看到"销售管理"菜单

    1.1.3例如:普通员工只能看见系统公告中公告查看

    2.2现实生活中的职位对应1个或多个数据库中的角色

    2.在系统上线后,会在程序中添加几种比较常见的角色,并把菜单和角色关联

    3.1以后每次新建用户时

    3.2在用户表中添加一个数据

    3.3在用户和角色关联表中添加1条或n条数据

    3.画图说明RBAC:

    三.RBAC具体实现

    [1]实现需求

    使用RBAC数据库设计思想,完成不同的用户登录系统后显示不同的菜单

    [2]功能分析

    用户:张三和李四

    菜单

    用户管理

        用户查询

        增加用户

    班级管理

        班级查询

        增加班级

    查看通告

        系统设置

    [3]数据库设计

    [4]数据库Sql语句

    /*用户表--新增角色rid*/

    /**角色表**/

    create table role(

        rid INT(5) PRIMARY KEY AUTO_INCREMENT,

        rname VARCHAR(55)

    );

    INSERT INTO role VALUES(DEFAULT,'管理员工');

    INSERT INTO role VALUES(DEFAULT,'管理员');

    /**菜单表**/

    CREATE TABLE menu(

        mmid INT(5) PRIMARY KEY AUTO_INCREMENT,

        mname VARCHAR(55),

        URL varchar(55),

        pid INT(5)

    );

    /**角色-菜单表**/

    create table role_menu(

        rid INT(5),

        MMID INT(5)

    );

    /*给不同的角色赋予菜单*/

    insert into role_menu values(1,2);

    insert into role_menu values(1,3);

    insert into role_menu values(1,6);

    insert into role_menu values(1,8);

    insert into role_menu values(1,9);

    insert into role_menu values(1,10);

    insert into role_menu values(2,1);

    insert into role_menu values(2,2);

    insert into role_menu values(2,3);

    insert into role_menu values(2,4);

    insert into role_menu values(2,5);

    insert into role_menu values(2,6);

    insert into role_menu values(2,7);

    insert into role_menu values(2,8);

    insert into role_menu values(2,9);

    insert into role_menu values(2,10);

    /*用户登录成功查询该角色下的所有菜单 用户登录成功就知道了rid=1*/

    /*在role_menu表中查询指定角色中所有菜单的id*/

    select mmid from role_menu where rid=1

    /*在去menu表中查询指定mmid对应的菜单*/

    select * from menu where mmid in(select mmid from role_menu where rid=2)and pid=1

    [5]代码效果实现

    5.1登录jsp页面

    <div style="margin-top:120px; margin-left:407px;">

        <div id="di" class="easyui-panel" title="登录" style="width:400px;height:300px;data-options="iconCls:'icon-help',closable:false,collapsible:false,minimizable:true,maximizable:true">

            <div style="text-align:center;margin-top:80px;">

                <form>

                    <div style="margin-bottom:25px;">

                        <span>用户名</span>

                        <input type="text" name="name" class="easyui-textbox" data-opyions="required:true"/>

                    </div>

                    <div style="margin-botton:25px;">

                        <span>密&nbsp;&nbsp码</span>

                        <input type="text" name="pwd" class="easyui-passwordbox" data-options="required:true"/>

                    </div>

                    <div>

                        <a onclick="javascript:void(0)" class="easyui-linkbutton" data-options="inonCls:'icon-clear'">提交</a>

                        <a onclick="javascript:void(0)" class="easyui-linkbutton" data-options="inonCls:'icon-clear'">清空</a>

                    </div>

                </form>

            </div>

        </div>

    </div>

    5.2Mapper层代码

    //查询菜单操作

    @Select("select * from menu where mmid in(select mmid from role_menu where rid=#{param1}) and pid=#{param2}")

    List<Menu> selectMore(int rid,int pid);

    5.3Service层代码

    @Override

    public List<Tree>findMoreMenu(int rid,int pid){

        List<Menu>list = menuMapper.selectMore(rid,pid);

        List<Tree> lsit2 = new ArrayList<>();

        for(Menu menu:list){

            Tree tree = new Tree(menu.getMmid(),menu.getMname(),menu.getState()==1?"open":"closed");

            //把指定的url地址保存到tree

            tree.setUrl(menu.getUrl());

            list2.add(tree);

        }

        return list2;

    }

    5.4Controller层代码

    @RequestMappoing("/findMoreMenus")

    public List<Tree>findMoreMenus(@RequestParam(defaultValue="0")int id,HttpSession session){

        User user = (User)session.getAttribute("user");

        return menuService.findMoreMenu(user.getRid(),id);

    }

    5.5运行截图

    四.RBAC详细版本

    [1]数据库设计

    1.1权限表:平时小型项目中可以省略

    1.2用户组表:对用户进行分组,每个用户组绑定多个角色,把用户放入到用户组后,具有对应多个角色

    1.3角色组:角色组对应多个角色,用户组和角色组

    1.4完成访问控制时,需要对什么类型表进行访问控制(在简单版中)把需要控制的内容和角色进行直接关联

    [2]详细版中是跟权限进行关联

    五.URL权限控制

    1.目前的问题

    访问通过URL非法操作,例如:在浏览器中直接通过URL访问控制器

    2.解决方案

    区分开:和页面元素可见权限

    2.1页面元素可见:在页面能不能看到某些内容

    2.2URL权限指:在浏览器地址栏直接访问

    3.实现思想(基于简单版)

    3.1添加URL表:

    3.2URL表和角色表进行关联

    3.3在filter或拦截器中天啊及权限验证

    4.代码实现实例

    4.1数据库设计

    在当前rbac案例中新增一张url权限信息表

    表名:t_url

    作用:存储需要被管理的url地址信息

    字段:编号,url地址

    在当前rbac案例中新增一张角色和url权限表的关联表

    表名:r_url

    作用:存储需要被管理的url地址和信息

    字段:编号,url地址

    在当前rbac案例总新增一张角色和url权限表的关联表

    表名:r_url

    作用:表名url和角色之间的关联关系

    字段:角色id,url的编号

    Sql语句实例:

    4.2代码实现

    实现思路:

    在项目增加过滤器,在过滤器中判断当前请求的url地址和用户具备的操作的URL地址是否一致.如果一致则放行,不一致则拦截,并提示器权限不足

    过滤器代码示例:

    public class LoginFilter2 implements Filter{

        @Override

        public void init(FilterConfig filterConfig)throws ServletException{

        }

        @Override

        public void doFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain)throws IOException,ServletException{

            //登录权限的校验

            HttpServeltRequest req = (HttpServletRequest)servletRequest;

            HttpServletResponse resp = (HttpServletResponse)servletResponse;

            //获取用户输入的名称

            String uri = req.getRequestURI();

            if("/ty/login.jsp".equals(uri)||"/ty/UserController/userLogin".equals(uri)){

                filterChain.doFilter(req,resp);

            }else{

                User user = (User)req.getSession().getAttribute("user");

                if(user!=null){

                    List<Url>list = user.getList();

                    for(Url u:lsit){

                        String url = "/ty/u.getUrl()";

                        System.out.println(url);

                        if(uri.equals(url)){

                            fileterChain.deFilter(req,resp);

                            return;

                        }

                    }

                    resp.getWriter().print("<script type='text/javascript'>alert('ERROR')</script>")

                }else{

                    //判断当前请求是否是ajax请求

                    if("XMLHttpRequest".equals(req.getheader("X-Requested-With"))){

                        System.out.println("ajax中Session跳转页面");

                        resp.setHeader("sessionstatus","timeout");

                        resp.setHeader("redirectUrl","/ty/login.jsp");

                    }else{

                        resp.sendRedirect("/ty/loging.jsp");

                    }

                }

            }

        }

        @Override

        public void destrop(){}

    }

    页面引入jquery ajax请求的通用代码(特定ajax请求处理后执行)

    $.ajaxSetup({

        contextType:"application/x-www-form-urlencoded;charset=utf-8",

        complete:function(XMLHttpRequest,textStatus){

            //通过XNLHttpRequest取得响应头,sessionstatus

            var sessionstatus = XMLHttpRequest.getResponseHeader("sessionstatus");

            if(sessionstatus=="timeout"){

                //这里怎么处理在你,这里跳转的登录页面

                window.location.replace(XMLHttpRequest.getResponseHeader("redirectUrl"));

            }

        }

    })

    相关文章

      网友评论

          本文标题:高级第八天:RBAC

          本文链接:https://www.haomeiwen.com/subject/kpglektx.html