# 权限定义
在进行权限定义之前,首先需要明确受控对象。受控对象是指在应用开发过程中需要进行权限控制的对象。例如导航菜单,页面元素,API 接口,数据等。在低代码开发平台中,要先定义好权限,再到相应的受控对象上进行配置。以前面章节开发的合同管理为例,我们要满足如下的权限控制需求,需要先定义权限。
场景一:功能控制
- 角色 A 可以查看合同列表,查看合同详情,新增合同,编辑合同,删除合同等操作;
- 角色 B 可以查看合同列表,不能新增合同,编辑合同,删除合同等操作;
场景二:接口访问控制
- 非授权角色用户无法调用接口;
场景三:数据权限控制
- 角色 A 可以看到所有合同;
- 角色 B 可以看到自己创建的合同;
当然,权限控制的场景远不止这些,本篇仅仅针对最常见的场景进行分析。
权限定义有些约定需要注意:
- 功能权限下面可以定义子功能权限,建议不超过两个层级;
- 资源权限只支持一个层级;
- 资源权限必须绑定操作(Actions)或者数据范围(DataScopes);
# 功能权限
功能权限是我们最常用的模式,它是对应用中的功能模块进行权限控制。例如:导航菜单,页面元素,接口访问控制等。 我们先在 更多》权限 中定义以下功能权限。

通过上述的定义,已经可以实现场景一 和 场景二 的需求了。
# 资源权限
资源权限是一种相对复杂和抽象的模式,通过它可以对接口和数据进行控制,当然也包含了控制导航菜单,页面元素等。资源权限需要和操作或者数据范围关联。正如上个章节介绍的,权限控制,本质上就是在保护资源(例如某个实体数据),要界定一个用户能对这些资源进行什么样的操作(查看/修改)。
# 1.创建操作
整个应用可以抽象出一些操作,例如下图的新增、修改、删除、导入、查询等操作,每个资源可能都会使用到。

# 2.创建数据范围
定义默认的数据范围。

设置数据规则,例如我创建的,所有等。

注意:规则表达式其实是一个SQL表达式,可以根据实际情况进行调整。
- 我创建的:created_by = :vars.user.id (当前用户创建的数据)
- 所有:1=1
:vars.user 可以拿到当前用户的信息,例如:id(用户ID),name(用户显示名称),username(用户登录名称),properties(其他属性,是个对象)等。
# 3.关联操作或者数据范围

通过上述的定义,我们就可以实现 场景三 的功能需求了。 细心的开发者也许会有个疑问,这里合同(contract)和合同实体(contract_entity) 的定义能否合在一起? 答案是可以的,直接用后者即可,覆盖了功能权限的定义范畴。对于一些简单的场景,功能权限完全可以满足需求了,也比较容易理解。
# 绑定权限
# 导航菜单
进入模块 》 导航页,对合同管理 绑定权限。

# 页面元素
选中页面的新增按钮,在属性栏配置权限即可。


无权限状态,可以选择隐藏或者禁用。如果是功能权限,可以通过 utils.hasPermission('功能权限编码') 判断是否有权限。如果是资源权限,可以通过 utils.hasPermission('资源编码.操作编码') 判断是否有权限。
# 接口访问权限
针对创建接口进行访问权限的控制,如果没有授予权限的情况下,请求接口将会返回 403 状态码。


# 接口数据权限
对接口返回的数据进行权限控制,需要关联资源权限和对应的操作。

注意:接口访问权限和接口数据权限是可以同时启用的。
另外,假如是基于SQL开发的接口,需要在SQL中加入@security安全因子来控制数据权限,框架会自动计算出sql表达式,例如:
select * from contract where @security
举个例子,当前用户被授予了我创建的数据范围权限,那么上述SQL会被转换为:
select * from contract where created_by = '当前用户ID'
# java数据权限
有些情况下,需要在java代码中进行权限控制,例如,在接口层通过 Dao 执行SQL代码实现数据权限控制,参考如下。
- 在controller层添加
@SecuredResource注解,指定资源权限编码; - 在方法上添加
@SecuredAction注解,指定操作编码; - 在SQL中添加
@security安全因子。
package com.example.demo.controller;
import fly.core.data.model.RowMap;
import fly.core.meta.annotation.Summary;
import fly.core.security.annotation.SecuredAction;
import fly.core.security.annotation.SecuredResource;
import fly.orm.dao.Dao;
import fly.orm.dao.query.SQLQuery;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/test")
@Summary("test api")
@SecuredResource("user_manager") // 资源权限编码
public class TestController {
@Autowired
Dao dao;
@GetMapping("/userlist")
@Summary("获取用户列表")
@SecuredAction("query") // 操作编码
public List<RowMap> getUserList() {
List<String> result = new ArrayList<>();
String sql = "select * from sec_user where @security"; // 安全因子
SQLQuery<RowMap> query = dao.createSQLQuery(sql);
List<RowMap> rmList = query.list();
return rmList;
}
}
# 角色授权
在角色管理中,选择对应的角色进行授权。

为资源权限指定操作,授予数据可操作的范围。
