# 权限定义

在进行权限定义之前,首先需要明确受控对象。受控对象是指在应用开发过程中需要进行权限控制的对象。例如导航菜单,页面元素,API 接口,数据等。在低代码开发平台中,要先定义好权限,再到相应的受控对象上进行配置。以前面章节开发的合同管理为例,我们要满足如下的权限控制需求,需要先定义权限。

场景一:功能控制

  • 角色 A 可以查看合同列表,查看合同详情,新增合同,编辑合同,删除合同等操作;
  • 角色 B 可以查看合同列表,不能新增合同,编辑合同,删除合同等操作;

场景二:接口访问控制

  • 非授权角色用户无法调用接口;

场景三:数据权限控制

  • 角色 A 可以看到所有合同;
  • 角色 B 可以看到自己创建的合同;

当然,权限控制的场景远不止这些,本篇仅仅针对最常见的场景进行分析。

权限定义有些约定需要注意:

  1. 功能权限下面可以定义子功能权限,建议不超过两个层级;
  2. 资源权限只支持一个层级;
  3. 资源权限必须绑定操作(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代码实现数据权限控制,参考如下。

  1. 在controller层添加@SecuredResource注解,指定资源权限编码;
  2. 在方法上添加@SecuredAction注解,指定操作编码;
  3. 在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;
    }

}

# 角色授权

在角色管理中,选择对应的角色进行授权。

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

顶部