RBAC简介

RBAC

BAC基于角色的访问控制,RBAC认为权限授权的过程可以抽象地概括为:Who是否可以对What进行How的访问操作

RBAC简介

基于角色的权限访问控制模型

在RBAC模型里面,有3个基础组成部分,分别是:用户、角色和权限。RBAC通过定义角色的权限,并
对用户授予某个角色从而来控制用户的权限,实现了用户和权限的逻辑分离(区别于ACL模型),极大
地方便了权限的管理:

  • User(用户):每个用户都有唯一的UID识别,并被授予不同的角色
  • Role(角色):不同角色具有不同的权限
  • Permission(权限):访问权限
  • 用户-角色映射:用户和角色之间的映射关系
  • 角色-权限映射:角色和权限之间的映射

RBAC支持三个著名的安全原则:最小权限原则、责任分离原则和数据抽象原则

  • 最小权限原则:RBAC可以将角色配置成其完成任务所需的最小权限集合
  • 责任分离原则:可以通过调用相互独立互斥的角色来共同完成敏感的任务,例如要求一个计账员和财务管理员共同参与统一过账操作
  • 数据抽象原则:可以通过权限的抽象来体现,例如财务操作用借款、存款等抽象权限,而不是使用典型的读、写、执行权限
    在这里插入图片描述
    优点:
  • 简化了用户和权限的关系
  • 易扩展、易维护
    缺点:
  • RBAC模型没有提供操作顺序的控制机制,这一缺陷使得RBAC模型很难适应哪些对操作次序有严格要求的系统

RBAC的3种模型

  • RBAC0,是最简单、最原始的实现方式,也是其RBAC模型的基础
  • RBAC1基于RBAC0模型,引入了角色间的继承关系,即角色上有了上下级的区别。
  • RBAC2基于RBAC0模型的基础上,进行了角色的访问控制。

简介JWT

http协议无状态的,所以需要sessionId或token的鉴权机制,jwt的token认证机制不需要在服务端再保留用户的认证信息或会话信息。这就意味着基于jwt认证机制的应用程序不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利,jwt更适用于分布式应用

1、前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个POST请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探
2、后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
3、后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可
4、前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)
5、后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等
6、验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果

JWT的优势
1、简洁:JWT Token数据量小,传输速度也很快
2、因为JWT Token是以JSON加密形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支

3、不需要在服务端保存会话信息,也就是说不依赖于cookie和session,所以没有了传统session认证的弊端,特别适用于分布式微服务
4、单点登录友好:使用Session进行身份认证的话,由于cookie无法跨域,难以实现单点登录。但是,使用token进行认证的话, token可以被保存在客户端的任意位置的内存中,不一定是cookie,所以不依赖cookie,不会存在这些问题
5、适合移动端应用:使用Session进行身份认证的话,需要保存一份信息在服务器端,而且这种方式会依赖到Cookie(需要Cookie 保存 SessionId),所以不适合移动端

jwt的组成部分
标准的jwt令牌分为三部分,分别是Header、payload、signature;在token字符串中使用.进行分割

  • Header的组成部分包括两点:参数类型jwt,签名的算法hs256
  • Payload的组成就是登陆用户的一些信息,和token发行和失效时间等;这些内容里面有一些是标准字段,你也可以添加其它需要的内容
  • Signature是先用Base64编码的header和payload,再用加密算法加密一下,加密的时候要放进去一Secret,这个相当于是一个密码,这个密码秘密地存储在服务端

JWT每部分的作用,在服务端接收到客户端发送过来的JWT token之后:

  • header和payload可以直接利用base64解码出原文,从header中获取哈希签名的算法,从payload中获取有效数据。
  • signature由于使用了不可逆的加密算法,无法解码出原文,它的作用是校验token有没有被篡改。服务端获取header中的加密算法之后,利用该算法加上secretKey对header、payload进行加密,比对加密后的数据和客户端发送过来的是否一致。注意secretKey只能保存在服务端,而且对于不同的加密算法其含义有所不同,一般对于MD5类型的摘要加密算法,secretKey实际上代表的是盐值
    JWT工作原理
    在这里插入图片描述

SpringBoot项目中登录流程

1、在登录验证通过后,给用户生成一个对应的随机token(注意这个token不是指jwt,可以用uuid等算
法生成),然后将这个token作为key的一部分,用户信息作为value存入Redis,并设置过期时间,这个过
期时间就是登录失效的时间
2、将第1步中生成的随机token作为JWT的payload生成JWT字符串返回给前端
3、前端之后每次请求都在请求头中的Authorization字段中携带JWT字符串
4、后端定义一个拦截器,每次收到前端请求时,都先从请求头中的Authorization字段中取出JWT字符串并进行验证,验证通过后解析出payload中的随机token,然后再用这个随机token得到key,从Redis中获取用户信息,如果能获取到就说明用户已经登录

SpringBoot原理

SpringBoot启动原理

创建springbootApplication对象

  1. 创建springbootApplication对象springboot容器初始化操作
  2. 获取当前应用的启动类型。
    1:通过判断当前classpath是否加载servlet类,返回servlet web启动方式
    2:webApplicationType三种类型:reactive响应式启动、none即不嵌入web容器启动,
    springboot放在外部服务器运行、servlet基于web容器进行启动
  3. 读取springboot下的META-INF/spring.factories文件,获取对应的ApplicationContextInitializer装
    配到集合
  4. 读取springboot下的META-INF/spring.factories文件,获取对应的ApplicationListener装配到集合
  5. mainApplicationClass获取当前运行的主函数
  6. 调用springbootApplication对象的run方法,实现启动,返回当前容器的上下文
  7. 调用run方法启动
  8. StopWatch stopWatch = new StopWatch()记录项目启动时间
  9. getRunListeners读取META-INF/spring.factores,将SpringApplicationRunListeners类型存到集合中
  10. listeners.starting()循环调用starting方法
  11. prepareEnvironment(listeners, applicationArguments);将配置文件读取到容器中。读取多数据源classpath:/、classpath:/config/、file:./、file:./config/底下。其中classpath是读取编译后的,file是读取编译前的支持yml、yaml、xml和properties
  12. Banner printedBanner = printBanner(environment);开始打印banner图,就是spring boot启动最开头的logo图案
  13. AnnotationConfigServletWebServerApplicationContext初始化对象
  14. 刷新上下文调用注解,refreshContext(context);
  15. 创建tomcat
  16. 加载springmvc
  17. 刷新后的方法,空方法,给用户自定义重写afterRefresh方法
  18. stopWatch.stop();结束计时
  19. 使用广播和回调机制告诉监听者springboot容器已经启动化成功,listeners.started(context);
  20. 使用广播和回调机制告诉监听者springboot容器已经启动化成功,listeners.started(context);
  21. 返回上下文
@SpringBootApplication组合注解

@SpringBootApplication除去元注解真正起作用的注解有@SpringBootConfiguration、
@EnableAutoConfiguration和@ComponentScan
注解是输出logo后,通过ApplicationContext初始化后的refreshContext方法注入实现的
@SpringBootConfiguration作用就是将当前类申明为配置类,同时还可以使用@bean注解将类以方法
的形式实例化到spring容器,而方法名就是实例名
@ComponentScan
@ComponentScan作用就是扫描当前包以及子包,将有@Component,@Controller,@Service,
@Repository等注解的类注册到容器中,以便调用
如果@ComponentScan不指定basePackages,那么默认扫描当前包以及其子包,而@SpringBootApplication里的@ComponentScan就是默认扫描,所以我们一般都是把springboot启动类放在最外层,以便扫描所有的类
@EnableAutoConfiguration
@EnableAutoConfiguration工作原理主要就是通过内部的方法,扫描classpath的METAINF/spring.factories配置文件,将其中的org.springframework.boot.autoconfigure.
EnableAutoConfiguration 对应的配置项实例化并且注册到spring容器
对应classpath的META-INF/spring/目录下配置文件
场景启动器starter
使用Spring框架开发项目带来的一些的问题

  • 依赖导入问题:每个项目都需要来单独维护自己所依赖的jar包,在项目中使用到什么功能就需要引入什么样的依赖。手动导入依赖容易出错,且无法统一集中管理
  • 配置繁琐:在引入依赖之后需要做繁杂的配置,并且这些配置是每个项目来说都是必要的,这些配置重复且繁杂,在不同的项目中需要进行多次重复开发,这在很大程度上降低了开发效率
    在导入的starter之后,SpringBoot主要完成了两件事情:
  • 相关组件的自动导入
  • 相关组件的自动配置
    这两件事情统一称为SpringBoot的自动配置
    starter的命名规范
  • 官方命名空间采用前缀定义方式spring-boot-starter-,例如spring-boot-starter-web、springboot-starter-jdbc
  • 自定义命名空间采用后缀定义方式-spring-boot-starter,例如mybatis-spring-boot-starter

starter的整体实现逻辑主要由两个基本部分组成:

  • xxxAutoConfiguration自动配置类,对某个场景下需要使用到的一些组件进行自动注入,并利用xxxProperties类来进行组件相关配置
  • xxxProperties某个场景下所有可配置属性的集成,在配置文件中配置可以进行属性值的覆盖

按照SpringBoot官方的定义,Starer的作用就是依赖聚合,因此直接在starter内部去进行代码实现是不
符合规定的,starter应该只起到依赖导入的作用,而具体的代码实现应该去交给其他模块来实现,然后
在starter中去引用该模块即可

自动配置类的工作过程

首先容器会根据当前不同的条件判断,决定这个配置类是否生效

  • 一但这个配置类生效;这个配置类就会给容器中添加相应组件
  • 这些组件的属性是从对应的properties类中获取的,这些类里面的每一个属性又是和配置文件绑定的
  • 所有在配置文件中能配置的属性都是在xxxxProperties类中封装着,配置文件可以配置什么内容,可以参照该前缀对应的属性类中的属性字段
    SpringBoot自动配置
    SpringBoot启动会加载大量的自动配置类
  • 首先可以看需要的功能有没有在SpringBoot默认写好的自动配置类当中
  • 再来看这个自动配置类中到底配置了哪些组件;只要要用的组件存在在其中,就不需要再手动配置了
    给容器中自动配置类添加组件的时候,会从properties类中获取某些属性。只需要在配置文件中指
    定这些属性的值即可
    • xxxxAutoConfigurartion自动配置类;给容器中添加组件
    • xxxxProperties:封装配置文件中相关属性
      @Conditional派生注解
      @Conditional派生注解作用:必须是@Conditional指定的条件成立,才给容器中添加组件,配置里的所
      有内容才生效
      @ConditionalOnMissingBean容器中不存在指定的Bean
      @ConditionalOnBean容器中是否存在指定的Bean
      @ConditionalOnMissingClass系统中没有指定的类
      @ConditionalOnClass系统中有指定的类
      @ConditionalOnProperty系统中指定的属性是否有指定的值
      … …

数据库设计

数据库设计是指对于一个给定的应用环境,构造最优的数据库模式,建立数据库及其应用系统,使之能够有效地存储数据,满足各种用户的应用需求,重要的是信息要求和处理要求。
数据库设计方法

  • 试凑法,依靠设计人员的工作经验
  • 规划化设计法,3NF
  • 计算机辅助设计法。PowerDesigner
    数据库设计阶段
  1. 需求分析。信息要求和处理要求,自顶向下的结构化分析法
  2. 逻辑结构设计。概念模型ER图
  3. 概念结构设计。数据模型:关系和非关系型模型
  4. 物理设计。存储安排和方法选择
  5. 实施阶段。编写模式、装入数据
    数据库SQL优化
    1、创建索引。对于查询占主要的应用来说,索引显得尤为重要。如果不加索引的话,那么查找任何哪怕只是一条特定的数据都会进行一次全表扫描,如果一张表的数据量很大而符合条件的结果又很少,那么不加索引会引起致命的性能下降。但是也不是什么情况都非得建索引不可,比如性别可能就只有两个值,建索引不仅没什么优势,还会影响到更新速度,这被称为过度索引。
    2、复合索引。由于mysql查询每次只能使用一个索引,所以虽然这样已经相对不做索引时全表扫描提高了很多效率,但是如果在多个列上创建复合索引的话将带来更高的效率。如果创建了area、age和salary的复合索引,那么其实相当于创建了(area,age,salary)、(area,age)、(area)三个索引,这被称为最佳左前缀特性。因此在创建复合索引时应该将最常用作限制条件的列放在最左边,依次递减。
    3、索引不会包含有NULL值的列。只要列中包含有NULL值都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此复合索引就是无效的。所以在数据库设计时不要让字段的默认值为NULL。
    4、使用短索引。对字符串列进行索引,如果可能应该指定一个前缀长度。例如有一个CHAR(255)的列,如果在前10 个或20 个字符内,多数值是惟一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。
    5、排序的索引问题。mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作;尽量不要包含多个列的排序,如果需要最好给这些列创建复合索引。
    6、like语句操作。一般情况下不鼓励使用like操作,如果非使用不可,like “%aaa%” 不会使用索引而like “aaa%”可以使用索引。
    7、不要在列上进行运算。例如select * from users where YEAR(adddate)<2023。将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此可以改成select * from users where adddate<‘2023-01-01’;
    8、不使用NOT IN和<>操作。NOT IN和<>操作都不会使用索引将进行全表扫描。NOT IN可以NOT EXISTS代替,id<>3则可使用id>3 or id<3来代替。
    SQL语句优化
    1、对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引
    2、应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如select id from t where num is null,最好不要给数据库留NULL,尽可能的使用 NOT NULL填充数据库。不要以为 NULL 不需要空间。
    3、应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。
    4、应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描,如将or查询修改为集合合并操作union
    5、in 和 not in 也要慎用,否则会导致全表扫描
    6、模糊查询可能会将导致全表扫描。例如like ‘%abc%’,若要提高效率,可以考虑全文检索。
    7、应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
    8、不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
    9、在使用索引字段作为条件时,如果该索引是复合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
    10、对于多张大数据量的表JOIN,要先分页再JOIN,否则逻辑读会很高,性能很差。
    11、索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。
    12、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连 接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。
    13、任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。
    14、尽量避免大事务操作,提高系统并发能力
    15、尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。

RBAC数据表设计

数据库 create database test default character set utf8mb4;
表和表之间的关系:1对1、1对多或者多对1、多对多
1对1实现方式
具体的实现方式有2种:共享主键和唯一外键。例如员工信息和登录账号
共享主键

create table if not exists tb_emps(
id bigint primary key auto_increment comment '雇员编号',
name varchar(32) not null comment '姓名',
sex boolean default 1 comment '性别',
education varchar(32),
birth date comment '出生日期',
hire_date date comment '入职日期',
salary numeric(8,2) comment '月薪'
)engine=innodb default c
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值