主题
后端 WEB API 脚本权限控制
后端 WEB API 脚本可以直接被 HTTP 请求调用,因此每个对外函数都应明确权限边界。不要只因为脚本文件能被访问,就认为文件里的所有 request_ 函数都可以安全执行。
权限控制分层
WEB API 脚本的权限控制分两层:
- 脚本文件入口控制:系统根据脚本文件所在位置和当前登录状态决定能否进入这个
.action文件。 - 请求函数业务控制:脚本文件内部的
request_函数负责判断当前用户能否执行当前业务操作。
系统不会为每个 request_ 函数自动分配或判断不同权限。例如,同一个 order.action.ts 中的 request_query、request_submit、request_delete 都共用同一个脚本文件入口;谁能查询、谁能提交、谁能删除,需要脚本开发者在函数内判断。
脚本文件入口控制
脚本文件是否能被访问,首先取决于脚本文件是否位于 public 目录。
| 脚本位置 | 系统入口控制 |
|---|---|
public 目录下 | 公开访问,不要求登录。 |
非 public 目录下 | 当前实现会要求用户已登录,避免未登录用户直接访问后端脚本。 |
注意
源码实现中,非 public 目录下的 .action / .action.ts 脚本入口只做登录兜底,不会像普通元数据文件一样自动对脚本内部函数逐个判断查看、提交、删除等业务权限。
因此:
- 公开接口才放到
public目录。 - 不希望匿名用户访问的接口,不要放到
public目录。 - 只要接口涉及业务数据、数据修改、导出、删除、审批、提交等操作,都应在
request_函数内再次判断权限。
在函数内判断业务权限
脚本中可以使用 svr-api/security 获取当前用户,并调用当前用户对象的权限判断方法。
常用方法:
| 方法 | 用途 |
|---|---|
security.isLogin() | 判断当前请求是否已登录。 |
security.getCurrentUser() | 获取当前用户;未登录时返回 null。 |
currentUser.checkAllowed(path, operation, true) | 判断当前用户是否拥有某个资源的操作权限;第三个参数为 true 时,无权限会抛出异常。 |
currentUser.checkPermission(path, operation) | 获取权限判断结果对象,可继续读取数据范围等信息。 |
类型说明可查看:
示例:按资源权限限制查询和删除
下面的示例把查询和删除放在同一个 WEB API 脚本文件中。两个函数共用脚本文件入口,但函数内部使用不同的权限操作。
ts
import security from "svr-api/security";
const ORDER_RESOURCE = "/DEMO/app/order.app";
function requireLogin() {
const user = security.getCurrentUser();
if (!user) {
throw new Error("请先登录后再访问该接口。");
}
return user;
}
export function request_query(request, response, params) {
const user = requireLogin();
// 允许有查看权限的用户查询订单。
user.checkAllowed(ORDER_RESOURCE, "view-basic", true);
return {
success: true,
data: queryOrders(params),
};
}
export function request_delete(request, response, params) {
const user = requireLogin();
// 删除属于数据操作,应使用比查看更严格的权限。
user.checkAllowed(ORDER_RESOURCE, "action-data-delete", true);
deleteOrder(params.id);
return { success: true };
}
function queryOrders(params) {
// 这里写实际查询逻辑。
return [];
}
function deleteOrder(id) {
// 这里写实际删除逻辑。
}设计建议
- 一个 WEB API 脚本可以放多个
request_函数,但每个函数都要按业务动作单独判断权限。 - 查询、提交、删除、导出等不同操作不要共用同一条权限判断。
- 写入、删除、导出类接口不要放在
public目录。 - 即使脚本文件放在非
public目录,也不要把“已登录”当成“有业务权限”。 - 需要按数据范围过滤结果时,先用
checkPermission(path, operation)取得权限结果,再结合getDataRange()处理可访问数据范围。
