關鍵詞:飛書多維表格、PHP 權限模型、RBAC、API 令牌隔離、數據安全

在企業內部把「飛書多維表格」當輕量級業務數據庫用時,權限粒度往往成為最後一道坎:
“能不能讓 A 組的組長在 PHP 後台一口氣維護 10 張表,而組員 B 只看得到其中 1 張?”
飛書原生權限做不到“組內再分層”,必須藉助業務系統做二次封裝。
本文給出一條可直接落地的「雙層權限」方案:PHP 後台負責上層過濾,飛書 API 負責底層兜底,1000 字講清模型、表結構、代碼片段與踩坑點。


一、總體思路:把“表格”當“資源”再跑一次 RBAC

  1. 用户 ⇨ 用户組 ⇨ 飛書表格,三層資源綁定。
  2. PHP 後台維護 user_table_perms 關係表,決定“能看到誰”。
  3. 飛書側只給 PHP 應用 app_token,且通過“用户維度臨時令牌”限制“能操作誰”。
  4. 前端列表、後端接口、飛書 API 三層全部做權限校驗,任一層拒絕都無法越權。

二、數據模型:4 張核心表夠用

-- 用户組
CREATE TABLE user_groups (
group_id   INT AUTO_INCREMENT PRIMARY KEY,
group_name VARCHAR(64) UNIQUE
);
-- 用户
CREATE TABLE users (
user_id   INT AUTO_INCREMENT PRIMARY KEY,
group_id  INT NOT NULL,
is_admin  TINYINT(1) DEFAULT 0,
email     VARCHAR(128) UNIQUE,
INDEX idx_group (group_id)
);
-- 飛書表格
CREATE TABLE feishu_tables (
table_id   VARCHAR(32) PRIMARY KEY, -- 飛書返回的 tblxxxx
app_token  VARCHAR(64) NOT NULL,   -- 飛書應用憑證
table_name VARCHAR(128),
group_id   INT NOT NULL
);
-- 用户-表格權限
CREATE TABLE user_table_perms (
id        INT AUTO_INCREMENT PRIMARY KEY,
user_id   INT NOT NULL,
table_id  VARCHAR(32) NOT NULL,
perm_type ENUM('view','edit') DEFAULT 'view',
UNIQUE KEY uk_user_table (user_id, table_id)
);

説明:

  • 管理員 is_admin=1 時,可在 user_table_perms 插入 N 行;普通用户只能插入 1 行。
  • 表格必須歸屬某一 group_id,避免跨組越權。

三、配置流程:10 分鐘完成“組管理員多表 / 普通用户單表”

  1. 超管在「用户組管理」新建「華東區銷售組」。
  2. 在「飛書表格管理」把 5 張多維表格批量綁定到該組。
  3. 勾選張三為「組管理員」,系統自動往 user_table_perms 寫入 5 行 edit 權限。
  4. 勾選李四為「普通成員」,下拉指定僅開放「客户跟進表」1 張,系統寫入 1 行 view 權限。
  5. 權限預覽頁可一鍵導出 Excel,方便審計。

四、代碼實戰:三處校驗缺一不可

① 登錄後取列表(偽代碼)

$userId  = $_SESSION['user_id'];
$groupId = $_SESSION['group_id'];
// 一次性查出用户可見的表格
$tables = DB::select(
'SELECT t.*, p.perm_type
FROM feishu_tables t
JOIN user_table_perms p ON t.table_id = p.table_id
WHERE p.user_id = ? AND t.group_id = ?',
[$userId, $groupId]
);

返回 JSON 給前端,管理員拿到 5 個對象,普通用户僅 1 個。

② 操作前再校驗(防 URL 偽造)

function checkTablePerm(int $userId, string $tableId, string $need = 'view'): bool
{
$row = DB::selectOne(
'SELECT perm_type FROM user_table_perms WHERE user_id = ? AND table_id = ?',
[$userId, $tableId]
);
if (!$row) return false;
return $need === 'edit' ? $row['perm_type'] === 'edit' : true;
}
// 在路由中間件調用
if (!checkTablePerm($userId, $inputTableId, 'edit')) {
http_response_code(403);
exit('無權限');
}

③ 飛書令牌範圍隔離(底層兜底)

PHP 後台通過飛書身份驗證換取 user_access_token 時,把 table_id 寫進 scope:

"scope": {
"table:tblxxxx": ["READ", "WRITE"]
}

即使前端拿到令牌直接調飛書 API,也只能操作被授權的那 1 張表。


五、前端交互:讓“看不見”等於“不存在”

  • 表格列表使用 v-if 控制,無權限卡片直接不渲染,避免“置灰”帶來的心理落差。
  • 打開表格後,工具欄按鈕根據 perm_type 動態生成:
  • view 僅顯示“查詢”、“導出”;
  • edit 再顯示“新增記錄”、“批量刪除”。
  • 所有寫操作走統一 fetch 攔截器,後端返回 403 時自動彈窗“請聯繫管理員開通權限”。

六、常見坑位與排查清單

現象

90% 原因

管理員只看到 1 張表

user_table_perms 只插了 1 行,需“批量同步”按鈕補錄

普通用户仍能看到全部

漏加 t.group_id = ? 條件,被 SQL 查出跨組數據

飛書返回“No permission”

app_token 未在飛書後台開通“多維表格”權限集合

令牌 403,但 PHP 已放行

臨時令牌 scope 寫錯,或 table_id 大小寫不一致


七、小結

  1. 把飛書表格當“資源”,PHP 跑一次標準 RBAC,模型簡單可維護。
  2. 管理員 / 普通用户的差異只體現在 user_table_perms 的行數,邏輯無分支,後期改需求只改數據。
  3. 飛書側只做“最低可用”授權,雙重 403 讓越權成本≈∞。
  4. 前端“看不見”、後端“不給過”、API“不認賬”,三層防護即可滿足絕大多數合規審計。

按本文搭完後,後續新增表格或人員,只需在 PHP 後台“勾勾選選”5 秒搞定,再也不用追着飛書管理員到處開權限了。祝實施順利!