springboot前后端分离后权限原理浅谈

1. 需求描述

最近在梳理springboot前后端分离后的权限管理问题。前段时间,已经把shiro的实现和spring security 的实现进行了初步的了解。如果深入细节,一个篇幅怕是不够。本文仅对权限管理的一些通用原理进行探讨。

2. 权限分类

在前后端分离之后,对于权限方面,主要存在两方面的权限:
(1)前端页面访问权限
(2)后台接口访问权限。

下面分别以页面权限和接口权限两个方面展开讨论。

3. 页面权限管理

页面权限管理,即前端的不同页面需要不同的页面访问权限,比如,某一个页面A,需要超级管理员才能访问;某一个页面B,需要管理员才能访问;某一个页面C,普通注册用户就能访问;某一个页面D,不需要认证就能访问。从这里,我们可以抽象出几个最基本的概念。某一个用户,拥有若干角色;而某一个角色能够访问若干页面。在数据库层面,对应了几张表,即 用户表,用户角色表,角色表,角色菜单表,菜单表。
那么,如何实现呢?
在回答这个问题之前,可以参考以下几篇文章:
(1)Vue动态加载组件的两类方式(import和require)
(2)Vue动态路由的后端实现(基于AOP的思路)
(3)Vue动态路由的前端实现
从这几篇文章中,不难发现。页面可以通过动态路由的方式来渲染。再结合上权限,很自然的想到了解决方案。即某一个用户登录认证成功后,一方面会返回一个token作为后续访问的凭证,另一方面,同时查询数据库,返回该用户角色对应的菜单列表。不同的用户,拥有不同的菜单列表。
某个用户的菜单列表返回前端后,在前端完成渲染,从而达到了页面权限管理的作用。当然,再细粒度一点,也是可以做的,即在页面中,某一个组件的渲染,也采用动态渲染的方式,即把该组件对应的渲染权限保存在数据库中,用户登录的时候,随着user对象一同返回前端,完成渲染。不过,页面权限和页面内组件权限,通常是两个不同层面的解决方案。思想是相通的。如果某个页面,限制某个角色才能访问,通常,该页面也就不对页面内组件再进行角色权限分配了(虽然可以实现,但明显增加了复杂性)。因为如果对页面内组件进行角色权限分配,就没有必要再对该页面进行上一层的可访问性动态渲染控制。通常情况下,某一个具体的页面权限控制,是从该两种方案中二选一的关系。即要么进行该页面的动态渲染,某些用户角色可以访问该页面,某些用户角色不能够访问该页面。要么对该页面内的组件进行权限控制,某些用户角色能够访问该页面内的某些组件,某些用户角色不能够访问该页面内的某些组件。
如果只进行了页面权限控制,而对后台接口没有进行权限限制。那么,如果一个用户登录系统后,通过该用户凭证,就可以无限制的访问后台接口(因为后台接口仅需要完成认证),通过模拟的浏览器软件,进行接口操作,可能会给系统带来很大的安全隐患。
那么,就得对后台的接口进行权限控制,以下将展开讨论。

4. 接口权限管理

这里的接口权限管理,主要指springboot中的后台接口的授权访问权限。那么,如何实现呢?
某一个用户登录的时候,会携带该用户名(用户id)以及密码(或是验证码)在后台完成密码比对,或是验证码比对,确认身份成功后(即认证成功后)会返回一个token信息,作为该用户的一个凭证返回前台,前台保存该用户的token信息,以后访问接口,携带该token进行访问。
在后台,该用户登录完成认证后,系统会查询数据库,获取该用户的角色列表,以及该角色列表对应的可访问接口的权限列表。后台把该用户的角色列表,以及对应权限列表注入spring容器里面。具体管理角色权限方式,可以用shiro,当然,也可以用spring security。在此基础之上,某一个用户登录,系统中就会保存该用户的角色列表,以及对应的权限列表。
但是,后台的接口权限验证方式,通常并不是对所有的接口都进行权限验证,比如,登录就是对所有的用户都可以访问的接口。如果用集合A来表示所有的接口集,集合B来表示需要权限才能够访问的接口集。显然,集合B 是集合A的 真子集。即在数据库中,需要保存一份集合B,即 权限表。这里可以做这样一个假定,假定 接口 和 权限 存在 1:1的关系,事实上,他们也是一对一的关系,因为这里从定义就可以看出,这里研究的就是接口的权限,一个接口就有一个接口的权限。 那么,在权限表(接口权限表)中,我们就可以把涉及到需要权限才能够访问的接口存在权限表中。
而仅有权限表也是不够的,我们还需要角色权限表,即某一个用户角色可以访问权限表中的一个子集C。另一个用户角色可以访问权限表中的另一个子集D。
回到刚才的话题,某一个用户登录,系统中就会保存该用户的角色列表,以及对应的权限列表。
那么,某一个用户登录认证成功后,再次访问其他接口的时候,如何判断该接口是需要授权才能够访问呢,还是不需要授权就可以访问。 在这里,有几种方案可供选择,这也是本文探讨的重点。主要有以下两种实现方式:
(1)在某一个接口上标明一个注解,表示该接口需要什么角色才能够访问,或者,该接口需要什么权限才能访问。那么,对于登录的用户,shiro或者spring security 会帮我们判断,该用户是否拥有该角色或是否拥有该权限,从而是通过该访问请求,还是拒绝该访问请求,当然,这个工作,也可以自己写一个切面去实现。
但是,这种方式存在一个缺点,就是接口的权限,无法一目了然的统一管理。即我们需要去翻阅代码,才知道哪个接口上标注了权限注解,哪个接口上没有标注权限注解。数据库中的权限表(接口权限表)中的权限,并不一定要全部标注在接口上。可能会有预留的情况。
(2)另一种方式是,接口上不添加注解。系统中保存一份需要权限访问的接口列表(从数据库查询)。即权限表中保存的是需要权限才能访问的所有接口列表。
从上得知,某一个用户登录,系统中就会保存该用户的角色列表,以及对应的权限列表。即保存了该用户对应的可以访问的接口权限列表。
那么,当该登录用户访问其他接口的时候,用aop拦截,判断该接口是否在需要权限才能访问的接口里面。如果不在,则通行;如果在,再判断该用户有没有该接口的权限。如果没有,则抛出没有权限的异常返回。如果有,则通行。
(3)当然,在这里还有另一种判断选择。同样接口上不添加注解。但在shiro或是spring security中注入的不是该用户拥有的接口权限,而是该用户被拒绝的接口权限。即在该用户登录的时候,在后台查询数据库,根据该用户拥有的权限接口,以及所有需要权限才能访问的接口,获取需要权限但该用户没有权限的接口,即该用户不能访问的权限接口。
在该用户访问其他接口的时候,在aop里面,判断该访问的接口是不是在拒绝权限的接口里面,如果是,则拒绝访问,否则,则通行。

以上三种方式,各有优缺点,在此不再展开。后续探讨后,再开篇幅进一步探讨权限相关的内容。

5. 结语

java后台开发,权限的重要性不言而喻。但参阅相关的博客发现,大多数的文章仅说明,shiro或是spring security的具体实现。而对其抽象的基本原理没有进行较好的描述,本文就是为了从抽象的角度,来描述springboot前后端分离后权限的实现原理,以及不同的算法选择。

6. 参考资源

(1)Vue动态加载组件的两类方式(import和require)
(2)Vue动态路由的后端实现(基于AOP的思路)
(3)Vue动态路由的前端实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/555823.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js异步请求php数据,原生JS发送异步数据请求实例详解

这篇文章主要为大家详细介绍了原生JS发送异步数据请求的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下在做项目的时候,有时候需要用到异步数据请求,但是如果这个时候没有框架的依赖,就需要用到原生JS进行…

MyBatis-Plus——增删查改

开发环境 IDEA JDK:1.8 Spring Boot:2.6.2 Maven:3.3.9 MySQL:8.0.23 数据库准备 CREATE DATABASE mybatis_plus_db;DROP TABLE IF EXISTS person; CREATE TABLE person(id BIGINT(20) NOT NULL COMMENT 主键ID, name VARCHAR(30) NULL DEFAULT NULL COMMENT 姓…

让程序员最爽的ThreadLocal使用姿势

一、常见场景 ​ 1、ThreadLocal作为线程上下文副本,那么一种最常见的使用方式就是用来方法隐式传参,通过提供的set()和get()两个public方法来实现在不同的方法中的参数传递。对于编程规范来说,方法定义的时候是对参数个数是有限制的&#x…

php 堆和栈示例,php中堆和栈的使用

这篇文章介绍的内容是关于php中堆和栈的使用,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下一、关于堆和栈的概念及区别这里参考上篇博客: 浅谈堆和栈的区别通过这篇文章,我们可以知道广义的堆和栈到底…

一场事故告诉你zookeeper和nacos谁更适合做注册中心

前言 ​ 在分布式系统中,注册中心充当着重要角色,是服务发现、客户端负载均衡中不可缺少的一员。注册中心除了能够实现基本的功能外,他的稳定性、可用性和健壮性对整个分布式系统的流畅运行影响重大。dubbo作为国内一款主流的分布式系统&…

mysql 排他,mysql 共享锁 排他锁 防插入锁

试验1事务1:#!/usr/bin/pythonimport timeimport MySQLdb;conn MySQLdb.connect(host"localhost",port3306,user"root",passwd"asdf",db"test",unix_socket"/data/mysql_3306/mysql.sock")cursor conn.cursor(…

MySQL操作之JSON数据类型操作详解

MySQL操作之JSON数据类型操作详解 这篇文章主要介绍了MySQL操作之JSON数据类型操作详解,内容较为详细,具有收藏价值,需要的朋友可以参考。 概述 mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了my…

Mysql执行计划含义,mysql执行计划介绍

烂sql不仅直接影响sql的响应时间,更影响db的性能,导致其它正常的sql响应时间变长。如何写好sql,学会看执行计划至关重要。下面我简单讲讲mysql的执行计划,只列出了一些常见的情况,希望对大家有所帮助。测试表结构&…

Http GET 请求参数中文乱码

Http GET 请求参数中文乱码 两种解决方式 第1种:代码里转换 String name request.getParamter("name"); String nameUtf8 new String(name.getBytes("ISO8859-1"), "UTF-8");第2种:修改Tomcat配置 TOMCAT_HOME/conf…

matlab randomsample,randperm和randsample函数用法对比

构建替代数据的时候,一种常见的思路是打乱原数据的排列次序,通过随机置换原数据的排列次序从而产生和原数据系列统计特征(如均值、方差、分布)一致的随机数据。具体到Matlab中,此思路的实现会涉及到两个命令:randperm和randsample…

SpringBoot的编码问题

第一种方式:直接在配置文件中设置浏览器的解析编码的格式 #设置字符编码 #开启springboot的http字符编码的支持 spring.http.encoding.enabledtrue #强制使用指定字符编码 spring.http.encoding.forcetrue #指定使用的字符编码 spring.http.encoding.charsetUTF-8第…

寄生虫php版,-PHP版SEO最新教材版排名DeDeCms寄生虫V90繁殖

今天视频教程演示说明下PHP寄生虫服务端的使用。主要在很多搭建的过程中会出错,今天主要就讲解下寄生虫配置常见的问题。那么同样也可以看下我们之前的通用版寄生虫使用教程[通用版教程在文件夹中有],本教程是针对PHP版本的寄生虫服务端进行配置演示。继…

SpringMVC请求参数乱码问题

post 请求方式&#xff1a; 在 web.xml 中配置一个过滤器 <!-- 配置 springMVC 编码过滤器 --><filter><filter-name>CharacterEncodingFilter</filter-name><filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter…

MySQL中 JSON 数据类型应用

前言 今天接触到mysql中json数据类型&#xff0c;之前不知道有这个类型&#xff0c;今天学习一下。 JSON我相信大家都已经很熟悉了&#xff0c;但在 MySQL中&#xff0c;直至 5.7 版本中&#xff0c;才正式引入 JSON数据类型。在次之前&#xff0c;我们通常使varchar或text数…

如何修改matlab中的语句,求大神帮忙看一下这个语句怎么改!!!!!

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼clcclearWimread(e:\matlab\aaa\1.jpg);imshow (W);I rgb2gray(W); % 灰度处理imshow (I);title(灰度图像);Jimnoise(I,salt & pepper,0.2); %椒盐噪声figureimshow (J) ;title(椒盐噪声);Qimnoise(I,gaussian,0,0.01); %高斯…

MySql中json类型的使用___mybatis存取mysql中的json

MySql中json类型的使用 MySQL从5.7.8起开始支持JSON字段&#xff0c;这极大的丰富了MySQL的数据类型。也方便了广大开发人员。但MySQL并没有提供对JSON对象中的字段进行索引的功能&#xff0c;至少没有直接对其字段进行索引的方法。本文将介绍利用MySQL 5.7中的虚拟字段的功能…

百度下拉词+php,百度下拉词是如何生成的?

我们在百度搜索某一词汇的时候&#xff0c;都会在搜索框下面弹出一些相关性和搜索次数比较多的语句或词语&#xff0c;我们在百度上搜索一下&#xff0c;就可以看到用户平时搜索习惯&#xff0c;搜索爱好是什么。护发下拉很多小伙伴就又有疑问了&#xff1a;这些下拉词是根据什…

python元组赋值给变量,Python的赋值

一、序列解包多个赋值操作同时进行&#xff1a;赋值多个值后面再遇到对多个变量赋值时&#xff0c;就不需要对一个变量赋完值再对另一个变量赋值了&#xff0c;用一条语句就可以搞定&#xff0c;例如&#xff1a;再次赋值由输出结果看到&#xff0c;x和y的值交换了&#xff0c;…

微服务,你得知道这

目录 一、业务场景介绍 二、Spring Cloud核心组件&#xff1a;Eureka 三、Spring Cloud核心组件&#xff1a;Feign 四、Spring Cloud核心组件&#xff1a;Ribbon 五、Spring Cloud核心组件&#xff1a;Hystrix 六、Spring Cloud核心组件&#xff1a;Zuul 七、总结 概述…

python新手输出错误,Python 新手常犯错误(第一部分)

用一个可变的值作为默认值这是一个绝对值得放在第一个来说的问题。不仅仅是因为产生这种BUG的原因很微妙&#xff0c;而且这种问题也很难检查出来。思考一下下面的代码片段&#xff1a;def foo(numbers[]):numbers.append(9)print numbers在这里&#xff0c;我们定义了一个 lis…