資源

租戶隔離與 RLS

Optserv 如何使用 Row-Level Security(RLS)強制公司範圍的資料存取——避免跨租戶資料外洩。

Optserv 是多租戶(multi-tenant)平台。多間公司會共用同一套資料庫基礎設施,但透過 Row-Level Security(RLS)實現彼此資料的完全隔離。

什麼是 RLS?

RLS 是 PostgreSQL 的一項功能,可在「資料庫查詢層」強制存取規則。與其依賴應用程式碼去過濾資料,RLS 讓資料庫本身以策略(policy)決定某位使用者能看見或修改哪些資料列。

有了 RLS,像 SELECT * FROM employees 這樣的查詢不會回傳整個資料庫的所有員工——它會自動只回傳「已驗證使用者所屬公司」的員工資料。

Optserv 如何使用 RLS

Optserv 的每張資料表都套用 RLS 策略。策略會檢查:

  1. 公司範圍 — 這筆資料是否屬於使用者的公司?
  2. 角色範圍 — 使用者的角色是否允許存取這筆資料?

例子:員工查詢出勤資料表時,只會看到符合 company_id = 自己公司 AND employee_id = 自己員工 id 的資料列。主管會看到自己部門的資料列。HR 會看到自己公司全部資料列。

關鍵點: 這些策略由資料庫引擎評估,不靠應用程式碼。即使應用程式出現 bug 不小心漏掉 WHERE 過濾,RLS 仍會阻止跨公司資料被回傳。

縱深防禦

RLS 是縱深防禦堆疊中的一層:

Request
  └── UI 顯示控管(角色感知導覽)
       └── 路由檢查(伺服器端驗證)
            └── Edge Function / RPC(寫入前驗證角色與公司)
                 └── RLS(資料庫層資料列過濾——永遠開啟)

資料要被存取或修改,四層都必須通過。任一層失效都會阻擋請求。

跨租戶隔離保證

任何已驗證使用者都無法查詢到其他公司的資料。RLS 策略中的 company_id 檢查會在每一次查詢中強制執行,包含:

  • 直接資料表查詢
  • 多表 join
  • 聚合與報表查詢
  • 寫入操作(INSERT、UPDATE、DELETE)

即使出現以下情況,隔離仍成立:

  • 應用程式碼 bug(漏加 WHERE)
  • 惡意或畸形的 API 請求
  • 非預期的查詢模式

學生與 RLS

OptClass 的學生帳號有獨立的 RLS 範圍。學生只能查到「自己的」紀錄——不會看到其他學生資料,更不可能看到任何員工資料。學生的 RLS 策略與員工 RLS 策略是分離的。