Spring Cloud + Vue前后端分离-第12章 通用权限设计

源代码在GitHub - 629y/course: Spring Cloud + Vue前后端分离-在线课程

Spring Cloud + Vue前后端分离-第12章 通用权限设计

这一章我们不依赖第三方框架,我会从权限相关表的设计,到权限的配置,到权限的拦截,带大家一步一步的做出一个通用的权限设计方案。

12-1 通用权限解决方案介绍

权限拦截的对象:用户

权限拦截的点:菜单、路由、接口、按钮

控制用户对资源的访问

权限的操作:配置、读取、拦截

100用户 * 100资源

直接用用户和资源做关联来控制权限,适合小型的项目,简单,快速

三个核心概念:用户、角色、资源

100用户 * 2个角色 + 2个角色 * 100资源

经典的权限管理设计:用户和角色关联,角色和资源关联

功能点:

配置:

用户管理:用户表,用户管理界面,已完成

资源配置:资源表,资源配置界面

角色管理:角色表,角色管理界面

用户角色关联配置:用户角色关联表,复用角色管理界面

角色资源关联配置:角色资源关联表,复用角色管理界面

两张关联表的配置,可以单独设计界面,也可以直接做到角色管理界面里。

读取:

用户权限的读取:用户登录的时候,读取该用户的所有权限。

登录时,通过用户角色关联表,可以知道当前登录用户的角色,再通过角色资源关联表就可以查到当前用户所有的资源

拦截:

用户操作业务时,进行权限拦截

前端界面:菜单,路由,按钮,hidden disabled

后端接口:接口,gateway的过滤器

疑问:前端已经对菜单和按钮做拦截,用户不能操作了,为什么还要对接口做拦截?

重要提示:所有前端的设计都是不安全的。

例登录名被修改了,说明我们的接口没有做登录名不可修改的校验,因为我们认为给登录名加了disabled就可以了,这是一个常见的安全隐患。

权限初始化

系统上线时,要初始化这五张表的数据。初始有一个用户能登录,能管理角色,管理资源,分配权限。

前面的章节的讲解模式是从简单的功能入手,再不断的扩展和完善,这一章,我们换一种模式,就会先分析需求,再列出功能点,明确总体要做哪些功能,再开始开发。

在实际工作中,也是用这种模式,我们还会加入团队评审的环节,确保我们的功能不会做歪了。

中高级面试题:请简单的设计一个权限管理功能,对初级人员来说会有点难,不过学完这一章,就不是问题了。

12-2 资源配置管理

资源表的设计与基本代码生成

1.通用权限管理:资源表的设计与基本代码生成

资源的名称一般是用页面上看得见的元素:菜单、按钮等。

all.sql

如果一个页面的所有操作统一控制权限,request可以填相关接口的前缀

生成代码

ResourceService.java报错原因:资源表的实体类是Resource和@Resource注解同名,导致冲突

admin.vue

router.js

测试

资源树的保存

1.通用权限管理:资源树的保存

资源点是开发阶段就确定的,所以并不是上线后再一个一个配置的。

资源管理最简单的一种方案:上线前准备好sql,刷库。

将资源管理做成资源树进行管理。

填入数据:带有层级结构的json字符串

resource.json

用法:以后开发新功能的时候,就在该文件里加入新的资源,可以上线前将新的资源json通过控台保存进数据库。

resource.vue

ResourceDto.java

ResourceService.java

将节点一个一个的取出来,放入list中

ResourceController.java

测试

资源树的显示

1.通用权限管理:资源树的显示

resource.vue

ResourceController.java

ResourceService.java

资源的保存是将树结构转成列表,重点是children属性;资源的显示是将列表转成树结构,重点是parent属性。

小知识:一边循环list,一边删除list中的对象,可以使用倒序循环。

list中有父节点的对象都会被remove掉,最终留下来的就是顶级的节点。

测试

12-3 角色权限管理

基本的角色管理功能

1.通用权限管理:增加基本的角色管理功能

2.资源列表补全

all.sql

admin.vue

router.js

resource.json

复制代码
[{
  "id" : "01","name": "系统管理",
  "children": [{
    "id" : "0101","name": "用户管理","page": "/system/user",
    "children": [
      {"id": "010101","name": "保存","request": ["/system/admin/user/list","/system/admin/user/save"]},
      {"id": "010102","name": "删除","request": ["/system/admin/user/delete"]},
      {"id": "010103","name": "重置密码","request": ["/system/admin/user/save-password"]}
    ]
  },
    {
      "id" : "0102","name": "资源管理","page": "/system/resource",
      "children": [
        {"id": "010201","name": "保存/显示","request": ["/system/admin/resource"]}
      ]
    },{
      "id" : "0103","name": "角色管理","page": "/system/role",
      "children": [
        {"id": "010301","name": "角色/权限管理","request": ["/system/admin/role"]}
      ]
    }]
},
  {
    "id" : "02","name": "业务管理",
    "children": [{
      "id" : "0201","name": "分类管理","page": "business/category",
      "children": [
        {"id": "020101","name": "增删改查","request": ["/business/admin/category"]}
      ]
    },
      {
        "id" : "0202","name": "课程管理","page": "business/course",
        "children": [
          {"id": "020201","name": "增删改查","request": ["/business/admin/course",
            "/business/admin/category/all,/business/admin/teacher/list","/file/f/course","/business/chapter"]}
        ]
      },{
        "id" : "0203","name": "讲师管理","page": "business/teacher",
        "children": [
          {"id": "020301","name": "增删改查","request": ["/business/admin/teacher"]}
        ]
      }, {
        "id" : "0204","name": "大章管理","page": "business/chapter",
        "children": [
          {"id": "020401","name": "增删改查","request": ["/business/admin/course","/business/admin/chapter"]}
        ]
      },
      {
        "id" : "0205","name": "小节管理","page": "business/section",
        "children": [
          {"id": "020501","name": "增删改查","request": ["/business/admin/section","/business/admin/chapter"]}
        ]
      }
    ]
  },
  {
    "id" : "03","name": "文件管理",
    "children": [{
      "id" : "0301","name": "文件管理","page": "file/file",
      "children": [
        {"id": "030101","name": "文件管理","request": ["/file/admin/file","/file/admin"]}
      ]
    }]
  }
]

测试

增加角色资源关联功能

1.通用权限管理:增加角色资源关联功能表,生成持久层和服务端代码

all.sql

点击[关联资源]按钮时,加载资源树

1.通用权限管理:点击[关联资源]按钮时,加载资源树

role.vue

测试

点击资源树模态框【保存】按钮时,保存角色资源关联表

1.通用权限管理:点击资源树模态框【保存】按钮时,保存角色资源关联表

role.vue

RoleDto.java

RoleService.java

RoleController.java

测试

打开资源树模态框时,加载角色资源关联数据,并自动勾选树节点

1.通用权限管理:打开资源树模态框时,加载角色资源关联数据,并自动勾选树节点

role.vue

批量操作的思路:先将原有的删除,再批量新增

RoleService.java

RoleController.java

测试

增加角色用户关联功能

1.通用权限管理:增加角色用户关联表,生成持久层和服务端代码

all.sql

点击【关联用户】按钮时,加载所有用户,弹出角色用户关联模态框

1.通用权限管理:点击【关联用户】按钮时,加载所有用户,弹出角色用户关联模态框

role.vue

测试

点击用户模态框【保存】按钮时,保存角色用户关联表

1.通用权限管理:点击用户模态框【保存】按钮时,保存角色用户关联表

role.vue

依赖vue的双向数据绑定特性,可以将复杂的页面操作变成简单的数据操作。很多前端框架都有双向数据绑定的特性,比如angular,微信小程序等。

RoleDto.java

RoleService.java

RoleController.java

测试

打开用户模态框时,加载角色用户关联数据

1.通用权限管理:打开用户模态框时,加载角色用户关联数据

role.vue

查关联表,得到的时userId,但是显示需要的是loginName。这里也可以通过写自定义mapper,把user表和role_user表关联得到loginName

RoleService.java

RoleController.java

测试

12-4 登录时获取资源权限

读取当前登录用户所属的角色的所有资源

1.通用权限管理:登录时,读取当前登录用户所属的角色的所有资源

LoginUserDto.java

一个资源可以会用到多个接口,多个资源的接口就可能重复,所以这里用Set去重

MyUserMapper.xml

MyUserMapper.java

UserService.java

测试

00000000

00000001

00000002

关于User的权限设置比较细,每个请求接口都可以单独控制。关于Resource的权限设置比较粗,所有接口用同一个request控制

12-5 权限拦截功能开发

前端界面权限拦截

前端界面权限拦截,完成用户管理

1.通用权限管理:前端界面权限拦截,完成用户管理

tool.js

admin.vue

在html中要使用vue方法,这个方法得在methods中定义

user.vue

测试

目前只修改了用户管理的权限拦截,以用户管理为例

00000000

每次修改权限配置,需要重新登录后才生效

前端界面权限拦截,完成所有界面控制

1.通用权限管理:前端界面权限拦截,完成所有界面控制

admin.vue

如果一个页面的所有按钮是统一控制的,那么只需要控制菜单就可以了,不需要给每个按钮加权限控制代码。

测试

路由权限判断

1.通用权限管理:前端界面权限拦截,增加路由权限判断

没有资源管理,但是我们可以直接通过路由进入

resource.json

复制代码
[{
  "id" : "00","name": "欢迎","page": "welcome"
},{
  "id" : "01","name": "系统管理",
  "children": [{
    "id" : "0101","name": "用户管理","page": "system/user",
    "children": [
      {"id": "010101","name": "保存","request": ["/system/admin/user/list","/system/admin/user/save"]},
      {"id": "010102","name": "删除","request": ["/system/admin/user/delete"]},
      {"id": "010103","name": "重置密码","request": ["/system/admin/user/save-password"]}
    ]
  },
    {
      "id" : "0102","name": "资源管理","page": "system/resource",
      "children": [
        {"id": "010201","name": "保存/显示","request": ["/system/admin/resource"]}
      ]
    },{
      "id" : "0103","name": "角色管理","page": "system/role",
      "children": [
        {"id": "010301","name": "角色/权限管理","request": ["system/admin/role"]}
      ]
    }]
},
  {
    "id" : "02","name": "业务管理",
    "children": [{
      "id" : "0201","name": "分类管理","page": "business/category",
      "children": [
        {"id": "020101","name": "增删改查","request": ["/business/admin/category"]}
      ]
    },
      {
        "id" : "0202","name": "课程管理","page": "business/course",
        "children": [
          {"id": "020201","name": "增删改查","request": ["/business/admin/course",
            "/business/admin/category/all,/business/admin/teacher/list","/file/f/course","/business/chapter"]}
        ]
      },{
        "id" : "0203","name": "讲师管理","page": "business/teacher",
        "children": [
          {"id": "020301","name": "增删改查","request": ["/business/admin/teacher"]}
        ]
      }, {
        "id" : "0204","name": "大章管理","page": "business/chapter",
        "children": [
          {"id": "020401","name": "增删改查","request": ["/business/admin/course","/business/admin/chapter"]}
        ]
      },
      {
        "id" : "0205","name": "小节管理","page": "business/section",
        "children": [
          {"id": "020501","name": "增删改查","request": ["/business/admin/section","/business/admin/chapter"]}
        ]
      }
    ]
  },
  {
    "id" : "03","name": "文件管理",
    "children": [{
      "id" : "0301","name": "文件管理","page": "file/file",
      "children": [
        {"id": "030101","name": "文件管理","request": ["/file/admin/file","/file/admin"]}
      ]
    }]
  }
]

admin.vue

第一次加载admin.vue时,需要判断路由权限,比如从登录页跳到控台主页,或者刷新控台主页时,会执行mounted.

进入控台主页后,发生子路由跳转时,会触发watch。

测试

后端接口权限判断

1.通用权限管理:增加后端接口权限拦截

在做登录功能时,我们也对接口做了登录校验,否则容易被绕开登录,直接调用后端接口。这里同样需要对接口做权限拦截

重新登录

可以通过搜索hidden,display:none等,来查看页面是否有隐藏元素

ctrl+f

可以删除成功,这是非常危险的

LoginAdminGatewayFilter.java

gateway里没有饮用server模块,所以没用LoginUserDto类。这里转成JSONObject进行操作

比如资源的保存:

path=system/admin/resource/save,

而配置的

request=system/admin/resource,

那么path.contain(request)就是true

测试

可以在vue的拦截器中,针对401返回码做判断,如果是401,就跳到登录页面

将业务场景变成程序代码

需求分析:最终要做成什么样子,如何使用这个功能。

功能点拆分:要实现这个需求,都有哪些功能点。

代码编写

团队内部评审通过后,为每个功能点评优先级,并估工时。

每天早上开展例会,每个人花几分钟的时间回答3个问题:

1.昨天做了哪些内容;

2.有没有遇到什么问题;

3.今天准备做哪些内容。

有问题一定要反馈出来,可以是遇到新技术了,或是功能点比想象中复杂,工时估少了等等。

相关推荐
腾讯TNTWeb前端团队3 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰6 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪7 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪7 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy7 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom8 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom8 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom8 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom8 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom8 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试