2025年rbac权限模型图(rbac权限管理实现)

rbac权限模型图(rbac权限管理实现)如果没有权限控制 系统的功能完全不设防 全部暴露在所有用户面前 用户登录以后可以使用系统中的所有功能 这是实际运行中不能接受的 所以权限控制系统的目标就是 管理用户行为 保护系统功能 那么如何进行权限控制呢 定义资源 创建权限 创建角色 管理用户 建立关联关系 定义资源 资源就是系统中需要保护起来的功能 具体形式很多 URL 地址 handler 方法



  • 如果没有权限控制,系统的功能完全不设防,全部暴露在所有用户面前,用户登录以后可以使用系统中的所有功能,这是实际运行中不能接受的。
  • 所以权限控制系统的目标就是:管理用户行为,保护系统功能。
  • 那么如何进行权限控制呢?
    • 定义资源
    • 创建权限
    • 创建角色
    • 管理用户
    • 建立关联关系

  1. 定义资源:资源就是系统中需要保护起来的功能。具体形式很多:URL 地址、handler方法、service 方法、页面元素等等都可以定义为资源使用权限控制系统保护起来。
  2. 创建权限:一个功能复杂的项目会包含很多具体资源,成千上万都有可能。这么多资源逐个进行操作太麻烦了。为了简化操作,可以将相关的几个资源封装到一起,打包成一个“权限”同时分配给有需要的人。
  3. 创建角色:对于一个庞大系统来说,一方面需要保护的资源非常多,另一方面操作系统的人也非常多。把资源打包为权限是对操作的简化,同样把用户划分为不同角色也是对操作的简化。否则直接针对一个个用户进行管理就会很繁琐。所以角色就是用户的分组、分类。先给角色分配权限,然后再把角色分配给用户,用户以这个角色的身份操作系统就享有角色对应的权限了。
  4. 管理用户:系统中的用户其实是人操作系统时用来登录系统的账号、密码。
  5. 建立关联关系:
    • 权限→资源:单向多对多
      • Java 类之间单向:从权限实体类可以获取到资源对象的集合,但是通过资源获取不到权限
      • 数据库表之间多对多:一个权限可以包含多个资源,一个资源可以被分配给多个不同权限
    • 角色→权限:单向多对多
      • Java 类之间单向:从角色实体类可以获取到权限对象的集合,但是通过权限获取不到角色
      • 数据库表之间多对多:一个角色可以包含多个权限,一个权限可以被分配给多个不同角色
    • 用户→角色:双向多对多
      • Java 类之间双向:可以通过用户获取它具备的角色,也可以看一个角色下包含哪些用户
      • 数据库表之间多对多:一个角色可以包含多个用户,一个用户可以身兼数职

2.1.没有中间表的情况

如果只能在一个外键列上存储关联关系数据,那么现在这情况无法使用 SQL 语句进行关联查询。

2.2. 有中间表

select t_studet.id,t_student.name from t_student left join t_inner on t_studen.id = t_inner.stuent_id left join t_subject on t_inner.subject_id=t_subject.id where t_subjct.id=1

2.3.中间表主键生成的方式

方式一:另外设置字段作为主键

方式二:使用联合主键(组合起来不能重复即可!)

鉴于权限控制的核心是用户通过角色与权限进行关联,所以前面描述的权限控制系统可以提炼为一个模型:RBAC(Role-Based Access Control ,基于角色的访问控制)。在 RBAC 模型中,一个用户可以对应多个角色,一个角色拥有多个权限,权限具体定义用户可以做哪些事情

3.1 RBAC0~RBAC3:4种权限模型介绍

  1. RBAC0:最基本的RBAC模型,RBAC模型的核心部分,后面三种升级版 RBAC 模型也都是建立在 RBAC0的基础上。
  2. RBAC1:在 RBAC0 的基础上增加了角色之间的继承关系。角色 A 继承角色 B 之后将具备 B 的权限再增加自己独有的其他权限。比如:付费会员角色继承普通会员角色,那么付费会员除了普通会员的权限外还具备浏览付费内容的权限。
  3.  RBAC2:在 RBAC0 的基础上进一步增加了角色责任分离关系。责任分离关系包含静态责任分离和动态责任分离两部分。
    1. 静态责任分离:给用户分配角色时生效
      1. 互斥角色:权限上相互制约的两个或多个角色就是互斥角色。用户只能被分配到一组互斥角色中的一个角色。例如:一个用户不能既有会计师角色又有审计师角色。
      2. 基数约束:
        一个角色对应的访问权限数量应该是受限的;一个角色中用户的数量应该是受限的 ;一个用户拥有的角色数量应该是受限的
      3. 先决条件角色:用户想拥有A角色就必须先拥有B角色,从而保证用户拥有 X 权限的前提是拥有 Y 权限。例如:“金牌会员”角色只能授予拥有“银牌会员”角色的用户,不能直接授予普通用户 
    2. 动态责任分离:用户 登录系统时生效
      • 一个用户身兼数职,在特定场景下激活特定角色:马云在阿里巴巴内部激活创始人角色;马云在某企业级论坛上激活演讲嘉宾角色 
  4. RBAC3:RBAC3 是在 RBAC0 的基础上同时添加 RBAC2 和 RBAC3 的约束,最全面、最复杂。

3.2 模型图解

        3.2.1基本RBAC模型

        3.2.2扩展RBAC模型

1.权限控制

2.给admin分配角色role

2.1目标:通过页面操作把 Admin 和 Role 之间的 关联关系保存到数据库。

2.2思路

2.3代码:前往分配页面

2.3.1创建保存 Admin-Role 关联关系的数据库表

 

这个表并不对应现实生活中或项目业务功能中的一个具体实体,所以没有对应的实体类,也不通过逆向工程做逆向生成

2.3.2修改 “ 分配 ”按钮

 

2.3.3创建 AssignHandler 

 

2.3.4 RoleServiceImpl中的方法

 

2.3.5 SQL 语句 

 

2.3.6 在页面上显示角色数据

 

2.3.7效果展示

2.3.8 调整表单让表单能够提交数据

 jquery代码:

 

2.4 代码:执行分配

2.4.1handler方法

 

2.4.2Service 方法

 

2.4.3 SQL 语句

 

2.4.4 修正 Bug

 

 

3.给role分配权限(auth)

3.1目标:把角色和权限的关联关系保存到数据库

3.2思路:

3.3代码:前往分配权限页面

3.3.1创建权限表:t_auth表,填充假数据

 

name 字段:给资源分配权限或给角色分配权限时使用的具体值,将来做权限验证也是使用 name 字段的值来进行比对。建议使用英文。
title 字段:在页面上显示,让用户便于查看的值。建议使用中文。
category_id 字段:关联到当前权限所属的分类。这个关联不是到其他表关联,而是就在当前表内部进行关联,关联其他记录。所以说,t_auth 表中是依靠 category_id 字段建立了“节点”之间的父子关系。

name 字段中值的格式:中间的“:”没有任何特殊含义。不论是我们自己写的代码
还是将来使用的框架都不会解析“:”。如果不用“:”,用“%、@、&、*、-”等等这样
的符号也都是可以的。 模块:操作名:user:delete

3.3.2 逆向工程生成资源:Auth、AuthExample、AuthMapper、AuthMapper.xml

3.3.3 创建角色到权限之间关联关系的中间表

 

3.3.4 创建分配权限模态框文件并引入

 

3.3.5 给 "☑" 绑定单击响应函数,用以打开分配权限模态框

 

3.3.6 在role-page.html中加入zTree的环境 

 

3.3.7  在my-role.js中编写函数: fillAuthTree()

 

3.3.8 后端代码:获取所有的权限信息

 

3.3.9 效果展示

 

 3.3.10 效果修正

 

3.3.11 把已经分配的权限进行回显(完整的fillAuthTree()代码)

 

3.3.12 后端代码

 

3.4 勾选权限,执行分配 

3.4.1给“执行分配”按钮绑定单击响应函数

 

3.4.2后端代码:执行分配权限

 

4.给menu分配权限(auth)(同role分配权限,略)

1.众筹项目加入 SpringSecurity 环境

1.1加入依赖

 

1.2在web.xml中加入Filter

 

1.3配置类CrowdfundingSecurityConfig 

 

1.4自动扫描的包(谁来把 CrowdfundingSecurityConfig 扫描到 IOC 里?)

考虑到权限控制系统更多的需要控制 Web 请求,而且有些请求没有经过 Service 方法,所以在SpringMVC的IOC容器中扫描CrowdfundingSecurityConfig。但是,SpringSecurity是有管理 Service、Dao 方法的能力的。

1.5 多个 IOC 容器之间的关系
①.问题描述:项目启动时控制台抛异常说找不到“springSecurityFilterChain”的 bean。

 

②.问题分析:
        Web 组件加载顺序:Listener→Filter→Servlet

        Spring IOC 容器:ContextLoaderListener 创建

        SpringSecurityFilterChain:从 IOC 容器中找到对应的 bean

        SpringMVC IOC 容器:DispatcherServlet 创建

DelegatingFilterProxy 查找 IOC 容器然后查找 bean 的工作机制:

ContextLoaderListener 初始化后,springSecurityFilterChain就在 ContextLoaderListener创建的 IOC 容器中查找所需要的 bean,但是我们没有在 ContextLoaderListener 的 IOC 容器中扫描 SpringSecurity 的配置类,所以 springSecurityFilterChain 对应的 bean 找不到。

③.问题解决:把两个 IOC 容器合二为一
将 ContextLoaderListener 取消,原本由 ContextLoaderListener 读取的 Spring 配置文件交给 DispatcherServlet 负责读取。

  • DelegatingFilterProxy 在初始化时查找 IOC 容器,找不到,放弃。
  • 第一次请求时再次查找。
  • 找到 SpringMVC 的 IOC 容器。
  • 从这个 IOC 容器中找到所需要的 bean。
 

遗憾的是:会破坏现有程序的结构。原本是 ContextLoaderListener 和 DispatcherServlet
两个组件创建两个 IOC 容器,现在改成只有一个。还有一种解决方案是:改源码。

修改 DelegatingFilterProxy 的源码,修改两处:

①.初始化时直接跳过查找 IOC 容器的环节

 

②.第一次请求的时候直接找 SpringMVC 的 的 IOC 容器

 

1.6 SpringSecurity 初始设置

 

2.登录

2.1 SpringSecurity 开启表单登录功能并前往登录表单页面 

①.登录表单

 

②.security设置

 

③.指定正确的账号和正确的密码(假数据)

 

④. 取消以前的自定义登录拦截器

 

2.2退出登录

 

2.3把内存登录(假数据)改成数据库登录

①.思路

②.代码体现

操作1:根据账号查询 Admin对象

 

操作2:根据 adminId 查询已分配的角色

 

操作3:根据 adminId 查询已分配权限

 

操作4 :创建 SecurityAdmin 类

 

操作5:MyUserDetailsService的完整代码

 

操作6:配置类CrowdfundingSecurityConfig中引入  UserDetailsService

 

操作7:密码加密

①MD5加密

 

②带盐值的加密

I.准备BCryptPasswordEncoder对象,放到IOC容器里面

 

操作8:使用BCryptPasswordEncoder在保存admin时加密

 

操作9:在页面上显示用户昵称

SpringSecurity处理完登录操作之后把登陆成功的User对象以principal属性名存入了UsernamePasswordAuthenticationToken对象。

 

2.4权限控制

操作1:设置测试数据(更改数据库)

 

操作2:给资源上锁

①.访问 Admin 分页功能时具备“经理”角色

 

效果:adminOperator可以访问,roleOperator不可以访问

②.访问 Role 分页功能时具备部长的角色

另一种方法:使用注解@PreAuthorize("hasRole('部长')")

 

注解生效的前提条件: 需要在配置类上加注解@EnableGlobalMethodSecurity(prePostEnabled = true),该注解表示启用全局方法权限控制功能,并且设置 prePostEnabled = true。保证@PreAuthority、@PostAuthority、@PreFilter、@PostFilter 生效

③.访问拒绝后的处理

这个结果为什么没有经过异常映射机制?

 所以要在 SpringSecurity 的配置类中进行配置

 

④.访问 Admin 保存功能时具备 user:save 权限

 

⑤.访问 Admin 分页功能时具备“经理”角色或“user:get”权限二者之一

 

其他注解(了解)
@PostAuthorize:先执行方法然后根据方法返回值判断是否具备权限。

例如:查询一个 Admin 对象,在@PostAuthorize 注解中和当前登录的 Admin 对象进行比较,如果不一致,则判断为不能访问。实现“只能查自己”效果。@PostAuthorize("returnObject.data.loginAcct == principal.username")使用 returnObject 获取到方法返回值,使用 principal 获取到当前登录用户的主体对象

@PreFilter:在方法执行前对传入的参数进行过滤。只能对集合类型的数据进行过滤。

@PostFilter:在方法执行后对方法返回值进行过滤。只能对集合类型的数据进行过滤。 

⑥. 页面元素的权限控制


                    
编程小号
上一篇 2025-03-03 11:57
下一篇 2025-03-10 16:17

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ri-ji/75587.html