前、后端分离权限控制设计与实现

简述

近几年随着react、angular、vue等前端框架兴起,前后端分离的架构迅速流行。但同时权限控制也带来了问题。

网上很多前、后端分离权限仅仅都仅仅在描述前端权限控制、且是较简单、固定的角色场景,满足不了我们用户、角色都是动态的场景。且仅仅前端进行权限控制并不是真正意义的权限控制,它只是减少页面结构暴露、增强用户体验的功效。

场景

系统为后台管理系统,包含了用户创建、用户登录、用户管理自己的资源。用户经常会新增、删除,也可以根据工作情况随时调整页面、功能权限,所以采用用户-角色-页面权限方案实现。

为什么不行:

  1. 根据前端路由表显示左侧菜单,但vue-router的路由表主要为了组织代码,经常我们所需要的菜单并非一致。比如某个前端路由a子路由有b、c,但菜单中我们想要直接一级菜单就显示b、c或者将b、c各放到其他菜单下。所以这种非常不灵活。

  2. 一个路由是菜单还是页面?是否需要显示到菜单中?是否验证权限?哪个角色或者用户拥有权限?这些都需要写到前端路由里面,一旦有任何权限变动就要大量调整代码。

  3. 如果权限写死在前端,那么角色或者用户必须已知且固定不变。比如页面1的meta增加属性标识可访问的角色为a和b

页面

一个页面即一个前端页面,比如首页、用户管理页、资源管理页等。

基本思路为:前端路由保持不变,数据库存储菜单结构、页面权限控制(可以直接做成一个页面来方便管理)等,前端根据数据库中的菜单结构和权限信息来渲染一个菜单出来并只显示其有权限的菜单,并在路由守卫中进行权限控制防止手动输入path越权打开页面

  1. 前端路由(vue-router)中需要正常创建页面及路由。

  2. 数据库存储菜单结构和页面权限信息,

    a.菜单(目录、非内容页)可以自己创建,不必要求前端路由中有,因为这是指菜单的可视化的组织结构

    b.页面(内容页)必须是前端路由中已有页面,因为这是用户需要访问的内容。

    c.菜单和页面组成上下级关系,一级可以是菜单也可以是内容页,内容页也可以放在菜单下,不可见的内容页也可以放在一个普通内容页下,这样理论(需要页面菜单样式支持)可以组成无限级菜单。面包屑导航也根据此层级递归查询得到。

    d.菜单和页面的基本属性包括title(对应路由title)、name(对应路由name)、path(对应路由path)、父级、类型(菜单/页面)、是否可见(左侧菜单栏是否显示:部分页面可能是页面内的链接进去)、是否需要验证权限(部分页面比如首页无需验证权限大家都可以进入)

    e.不需要控制权限且不需要显示到左侧菜单的路由这里可以不进行管理,比如404页面等

  3. 前台打开后获取获取数据库的所有菜单、页面及结构,根据是否登录、是否需要验证权限等进行控制,或无权限跳转至登录页

  4. 用户登录成功后,再获取用户对应的的页面权限列表,使用上一步获得的所有页面、结构和用户拥有权限的列表渲染出一个菜单,只包含此用户拥有权限的,提升用户体检,避免显示大量用户不能访问的菜单影响使用和不必要的功能暴露。

  5. 路由守卫中根据上一步获得的权限列表判断每个跳转,无权限可返回404或无权限页面,防止用户手动输入path越权访问

页面管理:

image.png

页面编辑:

image.png

功能

部分功能有事需要单独控制权限,比如用户管理页面可能允许多个角色查看,但是其中的“创建用户”功能只允许某一个角色使用,那么仅仅使用页面权限是不够。所以需要细粒度的功能权限控制。

网上的方案都是说:根据资源控制增、删、改、查等等,比如针对用户就是用户的创建、修改、删除、查询等。但是在我的实际使用中发现并不切合实际,最起码对像我这种管理后台,资源并不单纯的增删改查,可能有其他地方的其他操作中也会对此用户资源造成影响,比如禁用、删除角色也要禁用、删除用户,那么这个权限到底属于角色的权限还是属于用户的权限,或者后台又改了,角色又影响了其他资源或者不再对用户进行操作,都会影响权限控制。

所以更合理的方法应该为将每个功能单独进行控制并和页面进行关联,且不限定必须是增、删、改、查四种,可以任意定制,只需要与前后端开发约定一个唯一的标识即可。

如上的例子中,用户管理页面下有用户各种功能,角色管理页面中也有个角色禁用、删除功能,可以分别定义标识为role_disable、role_delete,如果拥有role_delete权限即可,即使没有user_delete权限,也可以直接删除用户,否则就不要给其role_delete权限。

用户登录后,从数据库获取其所拥有的的权限列表并存入vuex,包含页面和功能对应关系,例如页面name为user:{user: [‘user_delete’, ‘user_query’]},页面中根据删除按钮可以v-if="hasPermission(‘user_delete’)"判断即可

页面功能管理:

image.png

获取用户拥有的权限:

image.png

角色

一个角色类似于一个身份或岗位,每个角色有自己的权限范围。

  1. 一个角色可以拥有多个页面权限。

  2. 一个角色可以拥有多个功能权限。

角色管理:

image.png

角色分配权限:

image.png

用户

用户可以创建、删除,一个用户随时可能变更工作内容,或者身兼数职,所以可以为其分配一个或者多个角色,他拥有的角色的权限就是他的权限。此时已经可以打通权限前端的权限分配,用户-角色-页面权限、功能权限。

用户管理:

image.png

用户分配角色:

image.png

前端效果

前端页面菜单效果:

image.png

后端权限

传统前后端不分离的情况下,路由都在后端统一管理,简单的方法比如用户管理页面/user/那么他里面使用的接口都使用/user/add、/user/delete等相同前缀,那么只要判断用户拥有/user/权限就可以访问/user/*所有接口。

前后端分离后面临的问题:

1前、后端分别有自己的路由,且一个页面会同时调后端多个不同模块下的接口,这样一来就无法通过以上传统方式判断权限。

如此一来吗,就需要有前端页面到后端接口的管理,明确一个页面会调用哪几个接口。这样当授权用户页面时,系统就可以根据此关系推断哪些接口具有权限。

接口

方案:

  1. 需要控制权限的接口进行上传管理(可以做成管理页面)

  2. 每个页面和功能可以关联多个接口,比如用户页面关联了用户查询接口和用户编辑接口,用户删除功能关联用户删除接口

  3. 后端对请求的路径进行判断,用户->角色->页面/功能->接口,拥有接口权限即允许访问

  4. 前后端分团队开发,不容易一一对照,且前端有自己的路由(此路由受限于代码组织结构)等等,无法使用传统方式简单处理

  5. 相同的接口可能会被前端多个页面多次利用

接口管理:

image.png

页面关联接口、功能关联接口:

image.png

请求的接口无权限时:

image.png

接口后端权限控制

后端控制其实很简单,只要前面管理功能做好即可,基本逻辑为:

  1. 用户访问接口

  2. 判断用户和当前path,根据用户->角色->页面/功能->接口 得到当前用户有权限的接口列表与当前path相比

  3. 若无权限(某些接口只需要登录就能访问的,比如获取用户姓名信息的需要排除在外)则直接返回失败,前端全局捕获后给出无权限提示

数据库表示例

红色表为实体表,蓝色表为关联关系表。基本为用户->角色->页面/功能->后端接口

在这里插入图片描述

总结

  1. 用户管理

    a.用户增删改查

    b.每个用户分配一个或多个角色

  2. 角色管理

    a.角色增删改查

    b.每个角色分配一个或多个页面、功能授权

  3. 页面管理

    a.页面增删改查

    b.标记页面上下级结构、是否内容页(需对应前端存在的路由页面)、是否可见、是否控制权限等等

    c.前端菜单、面包屑等对用户可感知的内容根据此上下级结构等进行渲染,不必受限于前端代码中的路由

    d.前端路由根据此权限表进行权限控制

  4. 接口权限控制

    a.接口管理录入需要控制权限的接口

    b.将接口分别关联到页面、功能

    c.拥有功能权限则拥有对应接口权限,拥有页面权限则拥有对应的权限

    d.只要通过任意页面和功能拥有接口的权限则可以访问此接口

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

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

相关文章

风云php,t.php · 风云酷小子/js - Gitee.com

$ch curl_init();curl_setopt($ch, CURLOPT_URL, "http://zx.rcpx.cc/els/html/courseStudyItem/courseStudyItem.updateTimestepByUserTimmer.do");curl_setopt($ch, CURLOPT_HEADER, 1);curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);// post数据curl_setopt($ch,…

前后端分离必备的接口规范,十分接地气

1. 前言 随着互联网的高速发展,前端页面的展示、交互体验越来越灵活、炫丽,响应体验也要求越来越高,后端服务的高并发、高可用、高性能、高扩展等特性的要求也愈加苛刻,从而导致前后端研发各自专注于自己擅长的领域深耕细作。 然…

ubuntu php设置,关于ubuntu php环境设置详解-PHP问题

ubuntu php设置办法:起首更新源列表;而后关上“终端窗口”,输出饬令“sudo apt-get install php5”来装置php;接着装置设置装备摆设好apache环境,并装置php5-gd模块;最初创立“info.php”文件便可。Ubuntu …

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

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

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中的虚拟字段的功能…