分端实现权限控制
最常见的接口权限控制就是分端形式了,不同的端实现不同的接口,一个用户登录后,只能访问这个端的接口,而不能去访问其他端的接口.
例如:
商城有商家端,管理端,买家端,各个端之间账号互不相通.
每个端对订单的操作逻辑也不一样
用户端只能新建,查看订单
商家端只能查看订单,发货订单
管理端只能查看订单
代码结构大致为:
├── Admin 管理端 │ └── Order 订单 │ └── getList 查看订单列表 ├── Shop 商家端 │ └── Order 订单 │ ├── deliver 发货 │ └── getList 查看订单列表 └── User 管理端 └── Order 订单 ├── add 新增订单 └── getList 查看订单列表
这种权限控制的方法优点为: 通俗易懂,容易维护,项目复杂度不高,可以根据不同端来响应不同的字段
但是需要写更多的代码(查看订单写了3份,每次有字段改动都需要改动3份)
适合用户角色较少,分级明显的项目 (适合大多数项目)
rbac 权限控制
rbac其实百度已经很多了,我这边就大概说明下定义.
RBAC基于角色的访问控制(Role-Based Access Control )
按代码的方式来讲就是:
给角色赋予不同的权限,再通过给用户赋予不同的角色,来实现不同的权限控制.
例如 在一个企业中的货物管理系统中.
可能存在:
管理员:可操作所有权限
财务:管理货物价格
货物出入库管理员:货物出入库
货物主管:审核出入库
职工:申请货物
多个角色,如果按照分端来做的话,就需要分5个端甚至更多,同时查看货物的功能就需要写5份相同的代码.
这个时候,我们可以通过rbac权限控制的方法来做
代码结构为:
└── User 所有角色都是用户,需要登陆,通过数据库授权 ├── Apply │ ├── add 职工 │ ├── getList 职工,货物主管 │ └── verify 货物主管 └── Goods ├── add 管理员 ├── getList 货物管理员,财务,职工,货物主管 ├── takeOut 职工,货物主管 ├── update 管理员 ├── updatePrice 财务 └── updateNum 货物管理员
我们可以给一个用户赋予多个角色,例如职工也可能是货物主管,也可能还是货物管理员等等
通过这种多重角色赋予,角色授权模式,可以更好的动态赋予权限
完善方法,响应参数控制
那么这样就行了吗?
不,上面的是一个demo.并不完整
假设
在Goods/getList 中,不允许职工看到价格,只允许财务看到,
那么该怎么实现?
很明显,最简单的方法就是,写一个 getListForStaff再写一个 getListForFinance
那么又会问了,既然方法还是要写这么多,那rbac权限控制还有存在的必要吗?
rbac除了可以省几个通用方法之外,最重要的一点是用户多角色授权,所以还是有必要的
rbac实现步骤
#### role_list 角色表 - roleId \`int 11\` - roleName \`varchar 32 \` #### user\_role\_relation_list 用户角色关联表 (多对多) - relationId \`int\` - userId \`int\` - roleId \`int\` #### permission_list 权限表 - permissionId \`int\` - permissionName \`varchar 64\` - url \`varchar 64 /Api/User/add \` #### role\_permission\_relation_list 角色权限关联表 - relationId \`int\` - roleId \`int\` - userId \`int\` - permissionId \`int\` - authorizeType \`tinyint 1正向授权 2反向授权\`
主要表为这4个表,通过对用户授权角色
用户,角色间的权限关联叠加(反向授权>正向授权) 得到最后的权限列表,进行判断
此为后端表现形式,但是因为前端需要做管理菜单 显示/隐藏 等,所以还需要附带一个菜单管理功能:
#### menu_list 菜单表 - menuId \`int 菜单id\` - menuName \`varchar 菜单名称\` - permissionId \`int 授权id (如果为0则代表不受权限控制管理)\` - url \`varchar\` - pid \`int 父级id\` - level \`tinyint 菜单等级\` - displayMenu \`tinyint 是否显示菜单 有些 更新/新增 权限明显不是菜单,不需要显示出来\`
流程图: