高级第八天:RBAC

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页面

   

       

           

                

                    用户名

                   

                

               

                    密  码

                   

                

               

                    提交

                    清空

                

            

        

    

5.2Mapper层代码

//查询菜单操作

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

List

selectMore(int rid,int pid);

5.3Service层代码

@Override

public ListfindMoreMenu(int rid,int pid){

    List

list = menuMapper.selectMore(rid,pid);

    List 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 ListfindMoreMenus(@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){

                Listlist = 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("")

            }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)