Skip to content

后端 WEB API 脚本权限控制

后端 WEB API 脚本可以直接被 HTTP 请求调用,因此每个对外函数都应明确权限边界。不要只因为脚本文件能被访问,就认为文件里的所有 request_ 函数都可以安全执行。

权限控制分层

WEB API 脚本的权限控制分两层:

  1. 脚本文件入口控制:系统根据脚本文件所在位置和当前登录状态决定能否进入这个 .action 文件。
  2. 请求函数业务控制:脚本文件内部的 request_ 函数负责判断当前用户能否执行当前业务操作。

系统不会为每个 request_ 函数自动分配或判断不同权限。例如,同一个 order.action.ts 中的 request_queryrequest_submitrequest_delete 都共用同一个脚本文件入口;谁能查询、谁能提交、谁能删除,需要脚本开发者在函数内判断。

脚本文件入口控制

脚本文件是否能被访问,首先取决于脚本文件是否位于 public 目录

脚本位置系统入口控制
public 目录下公开访问,不要求登录。
public 目录下当前实现会要求用户已登录,避免未登录用户直接访问后端脚本。

注意

源码实现中,非 public 目录下的 .action / .action.ts 脚本入口只做登录兜底,不会像普通元数据文件一样自动对脚本内部函数逐个判断查看、提交、删除等业务权限。

因此:

  1. 公开接口才放到 public 目录。
  2. 不希望匿名用户访问的接口,不要放到 public 目录。
  3. 只要接口涉及业务数据、数据修改、导出、删除、审批、提交等操作,都应在 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) {
  // 这里写实际删除逻辑。
}

设计建议

  1. 一个 WEB API 脚本可以放多个 request_ 函数,但每个函数都要按业务动作单独判断权限。
  2. 查询、提交、删除、导出等不同操作不要共用同一条权限判断。
  3. 写入、删除、导出类接口不要放在 public 目录。
  4. 即使脚本文件放在非 public 目录,也不要把“已登录”当成“有业务权限”。
  5. 需要按数据范围过滤结果时,先用 checkPermission(path, operation) 取得权限结果,再结合 getDataRange() 处理可访问数据范围。
微信公众号微信公众号:山川软件