# 系统权限
本工程主要包含两方面的权限概念。
一个是菜单权限,一个是接口权限。
其中菜单权限是必须的,接口权限在个别要求不严谨的项目中,可以放低要求。接口权限主要用于控制API接口安全,防范部分黑客绕过你的WEB页面,直接向API发起越权漏洞攻击。
权限架构体系采用业内主流的RBAC
架构。
RBAC
是基于角色的访问控制(Role-Based Access Control
)在RBAC
中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
# 菜单权限
# 菜单维护
要控制菜单的权限,首先你需要建立起你自己的菜单体系。这个可以在WEB页中的系统维护 > 菜单列表
进行维护。
菜单列表是树形结构。新增页面如下图所示:
提示
图标指的是左侧菜单中需要显示的图标
动作中,单页面模式指的是直接在当前页打开,这也是最常用的模式,一般选择默认即可。多页模式指的是在新页面打开,类似于
a标签
的target="_blank"
。菜单名称指的是左侧菜单中显示的文字
跳转地址:
路由名称:使用
Vue Route
中命名的路由名称进行跳转。路由地址:使用可以直接在浏览器地址栏看到的,跟在哈希(
#
)后的URI
地址进行跳转。外部链接:可以使用全限定
URI
进行跳转,通常配合多页模式
。
# 给角色赋予菜单权限
接下来打开WEB页的系统维护 > 角色列表
,在你需要配置的角色右侧点击菜单
按钮,继续在里面勾选需要查看的菜单即可。
# 接口权限
# 权限维护
要控制接口权限,首先你需要维护好自己的接口权限。打开系统维护 > 权限列表
。如下图所示。
接口权限也是树形结构的,但却不一定要遵守这个约定,你也可以维护成一维的。
怎么理解这句话呢?
场景1: 如果你要删除用户,那么正常来讲你也必须拥有查看用户列表的权限。这样他们就组成了父子关系,有子(删除用户权限
)那必定就有父(查看用户列表权限
)。这时候你可以遵守树形约定。
场景2: 如果你要删除用户,但却不是在用户列表中进行操作。比如:你自己定义了一个页面,输入用户名称即可对该用户进行删除操作,这时候,实际上你不一定需要查看用户列表这个权限。所以这时候你可以不维护成树形约定。
总之,对于如何维护权限,暂时没有强制要求你怎么做。最简单的当然是不采用树形维护。只不过有个缺点,就是当权限多的时候,权限之间会产生一种无关联性,看上去会比较凌乱。
所以我建议你充分使用排序和描述两个字段。
描述的命名建议使用模块:权限名称
这种方式来命名,比如用户:删除
,用户:禁用
。这样会显得比较整齐。
提示
关于排序(其他模块通用
):
不建议你直接使用1,2,3,4,...,20这种连续方式维护。
你可以这样,比如用户权限是一个区间(1-100),菜单权限是另一个区间(101-200),依此类推。也就是不同模块间的间隔至少为100。
如果你第一次给用户权限维护了增删改查
4个接口权限(排序分别为101,102,103,104),后来你又需要新增一个用户禁用
的接口权限,你可以使用排序105。
这样做的好处就是,你可以保证同一模块的接口权限永远都排列在一起。
接下来,我们看下权限的新增页面。
权限名称:用于显示在列表中,取个合理的名称即可。
重点来看下对象
和操作
。
这两个属性是需要映射到API中的。权限框架采用的是Spring Security
。
如果你有接触过Apache Shiro
,应该知道shiro
的接口授权可以使用角色
和权限
两种。
但是我们已经有了自己的RBAC
体系,所以我这边将其简化了,我们只使用权限标识符
来进行用户的授权。因为有了用户的角色,我们可以很方便的推导出该用户的所有权限。
权限标识符的结构为对象:操作
,比如demo:delete
,表示demo的删除权限
。所以,你只需要在对象
属性中填写demo
,在操作
属性中填写delete
即可。
# API设定权限标识符
当然最重要的是,打开你的Conreoller
,找到你的删除接口,加上下述注解:
@ApiOperationSupport(author = "luosz@jfbrother.com", order = 7)
@ApiOperation(value = "示例表删除", notes = "示例表删除接口")
@ApiVersion(1)
@ApiImplicitParams({
@ApiImplicitParam(name = "ids", value = "主键id", required = true, dataType = "string", allowMultiple = true)
})
@DeleteMapping
@RolesAllowed({"demo:delete"})
public Result delete(@RequestBody @NotNull(message = "示例表id列表不能为空") @Size(min = 1, message = "示例表id至少存在一个") List<String> ids) {
service.delete(ids);
return ResultGenerator.genSuccessResult(ResultCode.NO_CONTENT);
}
2
3
4
5
6
7
8
9
10
11
12
注意
- RolesAllowed注解支持数组,也就是说可以维护多个权限标识符,如下表示拥有删除和更新的任意一种权限都可以访问该接口。
@RolesAllowed({"demo:delete","demo:update"})
- 很多情况下,同一个权限标识符是可以重用的。比如
用户的列表查看接口
和用户的单目录查看接口
均可赋值为同一个标识符user:query
可以看出具体的API接口和WEB上的权限实际上并不是一一对应的,他们的桥梁就是权限标识符
,标识符的维护是很灵活的,具体要看具体的业务情况来定。
总之,记住授权的原理:
根据当前登录用户查询角色,通过角色获得所有的权限标识符
,访问接口时,Spring Security
会自动分析,接口所需权限标识符是否在所有的权限标识符
中
# 给角色赋予接口权限
接下来打开WEB页的系统维护 > 角色列表
,在你需要配置的角色右侧点击权限
按钮,继续在里面勾选需要查看的权限即可。