有来技术团队2022-01-10 11:26:58博主文章分类:Spring Cloud©著作权
文章标签Spring Cloudspring微服务权限控制文章分类其它其它阅读数165
【 有来】开源全栈项目版本更新,本文部分内容和项目源码有出入,建议移步至 【Spring Cloud & Alibaba 实战 | 总结篇】Spring Cloud Gateway + Spring Security OAuth2 + JWT 实现微服务统一认证授权和鉴权,基于RBAC设计的适配微服务开发模式权限框架
hi,大家好,这应该是农历年前的关于开源项目有来商城 的最后一篇文章了。
有来商城 是基于 Spring Cloud OAuth2 + Spring Cloud Gateway + JWT实现的统一认证鉴权,Spring Cloud & Alibaba + vue-element-admin实现的微服务、前后端分离的全栈开源项目。
有来商城 的权限设计主要是为了实现以下几点目标:
有来商城 是基于Spring Boot 2.4、Spring Cloud 2020 & Alibaba、Vue、element-ui、uni-app快速构建的一套全栈开源商城平台,包括微服务应用、管理平台、微信小程序及APP应用。
项目预览地址: http://www.youlai.store
微信小程序体验码:
源码地址:
项目名称 |
Github |
码云 |
微服务后台 |
youlai-mall |
youlai-mall |
管理前端 |
youlai-mall-admin |
youlai-mall-admin |
微信小程序 |
youlai-mall-weapp |
youlai-mall-weapp |
APP应用 |
youlai-mall-app |
youlai-mall-app |
后台微服务
后台管理前端
微信小程序
应用部署
RBAC(Role-Based Access Control)基于角色访问控制,目前使用最为广泛的权限模型。
此模型有三个角色用户、角色和权限,在传统的权限模型用户直接关联加了角色层,解耦了用户和权限,使得权限系统有了更清晰的职责划分和更高的灵活度。
以下是 有来系统关于RBAC权限模型的数据库
用户和角色关系不用过多说明,这里重点说下权限,首先系统的权限分为3类,具体如下表:
权限名称 |
表名 |
字段 |
权限标识 |
菜单权限 |
sys_menu |
||
接口权限 |
sys_permission |
type=1 |
PUT_/users/** |
按钮权限 |
sys_permission |
type=2 |
system:user:add |
其实了解过目前主流开源系统的权限设计,大概率的把菜单和按钮放一块然后根据类别字段区分,以下就关于这种方式优劣发表下个人意见,仅供大家参考下不必较真:
优势:
劣势:
先看下vue-element-admin下的RBAC模型下的后台权限管理界面,体验地址: http://www.youlai.store
上文说到的关于权限表的拆分,菜单单独一张表,按钮权限和接口权限合为一张表根据类型type字段区分,之所以这样因为接口和按钮权限有些共性,都有一个权限标识字段。
至于按钮和接口为什么要区分呢?都使用system:user:add
权限标识不可以吗?
具体做法是接口方法加上Spring Security的注解@PreAuthorize("hasPermission('system:user:add')"),在执行方法前判断用户时候拥有该权限。
答案是一般场景这样设计绝对没问题。但这里使用网关作为统一鉴权的入口,肯定希望网关一次性把鉴权的活做的干脆利落,这样就不需要在各个微服务单独的把Spring Security权限模块引入鉴权,通过网关鉴权能把职责分工明确,减少开发工作量,无权限的请求直接被网关拦截返回,不会走到微服务那里再被告知无权访问,提高请求效率。
Spring Cloud Gateway网关使用请求路径Ant匹配请求标识进行权限判断的,例如/users/1
经过Ant匹配到权限标识/users/**
,而/users/**
是被用户所持有的权限标识,这就标识用户允许访问/users/1
的请求,所以和按钮的权限标识system:user:add
是有区别的。
这样就完事了吗?当然还没,因为 有来系统 较于其他系统它是比较严格遵守REST
接口设计规范,所以如果仅仅是上面根据请求路径URL判断权限肯定是不合理的,/users/1
这个请求路径在RESTful接口下可能是GET
类型的请求也有可能是PUT
类型的请求,那该如何处理?
所以在sys_permission表里还有一个method字段来标识请求方法类型,值可能会是、GET、POST、PUT、PATCH、DELETE等HTTP请求方法类型,其中是不限请求方法类型的意思,然后将请求方法类型和请求路径组合得到接口的权限标识是这样的PUT_users/1
。
接下来就通过对 有来系统 的实战操作来演示网关如何细粒度对RESTful接口的权限控制。
新增用户管理的增删改查权限
赋予系统管理员(admin)用户查询
权限,无其他权限
项目启动查看Redis中的角色权限规则:
看到系统管理员这个角色是没有用户修改权限的。你可以给角色添加用户修改权限后尝试是否可以修改成功。
admin
系统管理员登录执行一个用户修改
的提交的请求,看一下网关鉴权的流程:
结果可想而知,系统管理员不具有修改用户PUT_/youlai-admin/v1/users/2
权限,从缓存查询只有超级管理员具有该接口请求方法访问权限。页面结果显示如下:
Vue除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。
这里主要使用Vue.directive
注册一个全局自定义指令v-has- permission
用于权限判断,然后在模板中的任何元素使用v-has- permission
属性。
自定义指令学习传送门
完整代码: youlai-mall-admin
登录成功时获取用户信息,其中包含该用户拥有的权限字符串集合如下:
这里将用户权限拥有的字符串集合缓存到vuex的perms属性中:
有来管理前端 是基于vue-element-admin
后台前端解决方案,在vue-element-admin
项目我们可以看到自定义指令的应用。如下:
然后复制一份permission.js
重命名为hasPermission.js
,修改后如下:
import store from '@/store'
// 校验用户是否拥有按钮权限
function hasPermission(el, binding) {
const {value} = binding
const perms = store.getters && store.getters.perms
if (value && value instanceof Array) {
if (value.length > 0) {
const requiredPerms = value
const hasPermission = perms.some(perm => {
return requiredPerms.includes(perm)
})
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
}
} else {
throw new Error(`need perms! Like v-has-permission="['system:user:add','system:user:edit']"`)
}
}
export default {
inserted(el, binding) {
hasPermission(el,binding)
},
update(el, binding) {
hasPermission(el,binding)
}
}
注册hasPermission
至全局指令:
指令在组件上的应用:
系统管理员是没有修改
按钮的权限的,结果如下页面不显示修改按钮。
那给系统管理员添加修改
按钮的权限,再看看用户页面的显示情况
此时用户页面的修改按钮已经显示出来了,至此完成了系统的按钮权限控制。
本篇通过实战的方式讲述如何基于Spring Cloud Gateway + vue-element-admin技术设计一套符合RBAC规范的权限管理系统,通过网关就可以轻易实现RESTful接口方法细粒度的控制,无需将Spring Security模块引入各个微服务;以及使用Vue的自定义指令在组件中使用实现细粒度的按钮权限控制。
如果你对此系统权限设计有更好的建议,欢迎留言给我,在此感谢!如果对项目感兴趣的话,欢迎加我微信和项目交流群。
最后预祝大家新年愉快,有个完美充实的小假期。