美团一面:说说前后端分离权限控制设计和实现思路?

androidstarjack androidstarjack     2022-11-29     544

关键词:


 

 

点击上方关注 “终端研发部

设为“星标”,和你一起掌握更多数据库知识

来源:8rr.co/9QUT

# 简述

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

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

# 场景

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

为什么不行:

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

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

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


# 页面

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

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

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

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

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

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

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

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

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

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

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

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

页面管理:

页面编辑:


# 功能

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

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

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

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

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

页面功能管理:

获取用户拥有的权限:


# 角色

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

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

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

角色管理:

角色分配权限:


# 用户

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

用户管理:

用户分配角色:


# 前端效果

前端页面菜单效果:


# 后端权限

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

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

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

如此一来吗,就需要有前端页面到后端接口的管理,明确一个页面会调用哪几个接口。这样当授权用户页面时,系统就可以根据此关系推断哪些接口具有权限。微信搜索终端研发部获取2021年面试大全

# 接口


方案:

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

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

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

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

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

接口管理:

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

请求的接口无权限时:


# 接口后端权限控制

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

  1. 用户访问接口

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

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


# 数据库表示例

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

今日好文推荐

GitHub上非常实用的40个开源JAVA项目
XShell收费太贵?快试试开源的NuShell,好用!

GET 和 POST请求的本质区别是什么?看完觉得自己太无知了...
MyBatis批量插入数据你还在用foreach?你们的服务器没崩?

点个在看少个 bug 👇

一文读懂前后端分离权限控制设计和实现思路!(代码片段)

...QUT#简述近几年随着react、angular、vue等前端框架兴起,前后端分离的架构迅速流行。但同时权限控制也带来了问题。网上很多前、后端分离权限仅仅都仅仅在描述前端权限控制、且是较简单、固定的角色场景,满足不了我... 查看详情

企业管理系统前后端分离架构设计系列一权限模型篇(代码片段)

原文:企业管理系统前后端分离架构设计系列一权限模型篇前段时间分别用vue和react写了两个后台管理系统的模板vue-quasar-admin和3YAdmin。两个项目中都实现了基于RBAC的权限控制。因为本职工作是后端开发,比较清楚权限控制一个管... 查看详情

企业管理系统前后端分离架构设计系列一权限模型篇(代码片段)

...心功能,而且是可以做到通用的。打算写写关于管理系统前后端分离方面的文章,也是做一个知识的总结,其中会涉及到vue,react,node,.netcore等方面的知识。术语描述用户(S 查看详情

springboot+vue+shiro实现前后端分离权限控制

...Controller层还必须返回Freemarker模版的ModelAndView,逐渐有了前后端分离的想法,由于之前,没有接触过,主要参考的还是网上的一些博客教程等,初步完成了前后端分离,在此记录以备查阅。一、前后端分离思想前端从后端剥离,... 查看详情

springboot+vue+shiro实现前后端分离权限控制

...Controller层还必须返回Freemarker模版的ModelAndView,逐渐有了前后端分离的想法,由于之前,没有接触过,主要参考的还是网上的一些博客教程等,初步 查看详情

springboot+jwt+springsecurity前后端分离实现权限控制

参考链接:https://www.cnblogs.com/jinbuqi/p/11021971.htmlhttps://blog.csdn.net/I_am_Hutengfei/article/details/100561564 查看详情

springboot+springsecurity+jwt实现前后端分离登录认证及权限控制(代码片段)

借鉴文章:Springboot+SpringSecurity实现前后端分离登录认证及权限控制_I_am_Rick_Hu的博客-CSDN博客_springsecurity前后端分离登录认证最近一段时间,公司给我安排了一个公司子系统的后台管理系统,让我实现权限管理。此... 查看详情

前后端分离项目中springboot集成shiro实现权限控制

文章目录​​使用注解控制鉴权授权​​​​使用url配置控制鉴权授权​​​​表结构​​​​jar包依赖​​​​代码说明​​​​身份认证​​​​权限认证​​​​跨域问题解决​​​​登录验证不进行重定向改为设置http... 查看详情

前后端要不要分离以及如何做

前后端分离要不要搞?这个我觉得按照康威定律办就好了,前后端如果是两拨人,不要多想一定要分离,如果是一拨人,确定前后端是否要分离需要算账,收益是它会强制我们按照服务的理念指导系统设计,将来的微服务也就顺理成章,代... 查看详情

spingsecurity前后端分离两种方案

前言本篇文章是基于SpringSecurity实现前后端分离登录认证及权限控制的实战,主要包括以下四方面内容:SpringSeciruty简单介绍;通过SpringSeciruty实现的基于表单和Token认证的两种认证方式;自定义实现RBAC的权限控制;跨域问题处理;S... 查看详情

第一步:类似前后端分离的基础框架思路

...级互联网私有云应用,就没有考虑Vue.js+node.js来实现真的前后端分离,关键是考虑后期的二次开发及实施维护成本。但对于公有云部分则使用Vue.js+node.js来进行开发与部署。前端:jquery+bootstrap+bootstrap- 查看详情

springsecurity系列4基于springwebflux集成springsecurity实现前后端分离无状态restapi的权限控制原理分析

源码传送门:https://github.com/ningzuoxin/zxning-springsecurity-demos/tree/master/02-springsecurity-stateless-webflux一、前言在上一篇,我们基于SpringWebflux集成Spri 查看详情

vue前后分离动态路由和权限管理方案

需求需要根据不同的角色来显示不同的菜单问题系统是前后分离模式开发的,出现了后端接口和前端路由都需要权限管理。思路后端的接口肯定得验证权限前端的路由通过后端发回的json动态生成,对于比较细粒度的可以通过css... 查看详情

为什么要进行前后端分离?

一、认识前后端分离可能很多人会有误解,认为web应用的开发期进行了前后端开发工作的分工就是前后端分离。但其实前后端分离并不只是开发模式,而是web应用的一种架构模式。在开发阶段,前后端工程师约定好数据交互接口... 查看详情

博客基于springboot+vue的前后端分离颜值博客系统

...理发布文章文章列表分类管理标签管理消息管理评论管理说说管理说说列表发布说说用户管理用户列表在线用户权限管理角色管理接口管理菜单管理系统管理网站管理定时任务友链管理关于我相册管理日志管理个人中心三、技术... 查看详情

微信小程序前后端分离怎么实现

微信小程序前后端分离的主要实现方式是将前端和后端的代码逻辑分开,前端负责展示和交互,后端负责数据处理和逻辑控制。下面简单介绍一下微信小程序前后端分离实现的一些关键步骤:1.前端代码开发:使用微信小程序开... 查看详情

前后端分离

对于前后端分离的应用场景,不是所有的场景都适合,但是大多数项目都能够通过前后端分离来实现。大多数后台应用我们可以做成SPA应用(单页应用),而单页应用最主要的特点就是局部刷新,这通过前端控制路由调用AJAX,... 查看详情

vue发布中的前后端分离和前后端不分离

前后端分离思路:前端和后台完全分离.前端提供静态的css和js,在运行时将css和js给后端,后端进行数据的请求(ajax)前后端分离就是前端和后台在不同的服务器上。基本是前端一个nginx加css和js后端nginx加index.html当用户访问的时候... 查看详情