Files
medical-mall/pages/mall/admin/docs/sql/05_rls_permissions_matrix.md

4.4 KiB
Raw Blame History

05 RLS 权限矩阵Supabase 行级安全)

本节整理 complete_mall_database.sql 中的 RLSRow Level Security启用范围与策略意图并给出“角色 ×× 操作”的矩阵化视角,便于前后端对齐。

说明:该库采用 Supabase 模式,常用 auth.uid() 获取当前登录用户的 auth id并通过 ak_users.auth_id 映射到业务用户 ak_users.id


1. RLS 设计目标

  • 默认拒绝:启用 RLS 后,如果没有策略,访问会被拒绝。
  • 数据隔离优先:用户私有数据只能访问自己的行。
  • 商家/用户双视角:订单可被“买家”和“卖家”访问。
  • 公共可见数据受限:商品仅公开上架数据。

2. 启用 RLS 的表(来自 complete_mall_database.sql

脚本显式启用 RLS

  • ml_user_profiles
  • ml_user_addresses
  • ml_shopping_cart
  • ml_user_favorites
  • ml_browse_history
  • ml_user_coupons
  • ml_orders
  • ml_products

备注:其他表(如 ml_categories/ml_brands/ml_shops/ml_order_items 等)在该脚本片段中未显式启用 RLS。


3. 核心策略模式pattern

3.1 “归属自己”的通用模式

对用户私有表(档案、地址、购物车、收藏、浏览、券)使用类似逻辑:

  • SELECT/UPDATE/DELETE:要求当前 auth.uid() 对应到该行的 user_id
  • INSERT:要求插入行的 user_id 也属于当前 auth.uid()

概念表达(伪 SQL

-- 伪表达:当前登录者只能操作 user_id 属于自己的行
auth.uid() = (select auth_id from ak_users where id = <row.user_id>)

价值:

  • 前端直连 DB 时,就算请求参数伪造 user_id,也无法读写别人的行。

3.2 “订单:买家/卖家都可访问”模式

订单 SELECT 策略允许 auth.uid() 属于 user_idmerchant_id

auth.uid() in (
  select auth_id from ak_users where id in (user_id, merchant_id)
)

价值:

  • 买家能看自己的订单
  • 商家能看自己店铺相关订单(在当前“单商家订单模型”下成立)

3.3 “商品:公开上架,商家管理自己的”模式

  • SELECT:仅 status = 1 的商品可见
  • INSERT/UPDATE/DELETE:要求 merchant_id 属于当前登录商家

4. 权限矩阵(建议口径)

说明:此矩阵从业务语义出发描述“期望权限”。实际是否满足,还取决于:

  • 是否启用 RLS
  • 是否存在相应策略
  • ak_users 中角色定义与 auth_id 映射是否正确

4.1 角色定义

  • Customer消费者:普通用户
  • Merchant商家:拥有商品与订单管理权限
  • Admin管理员:平台管理(通常需要 service role 或额外策略)

4.2 表级矩阵(读/写)

ml_user_profiles

  • Customer
    • SELECT:仅本人
    • INSERT/UPDATE/DELETE:仅本人
  • Merchant
    • 同 Customer如果商家也是用户
  • Admin
    • 建议:通过 service role 或单独策略可读全量

ml_user_addresses

  • Customer
    • SELECT/INSERT/UPDATE/DELETE:仅本人

ml_shopping_cart

  • Customer
    • SELECT/INSERT/UPDATE/DELETE:仅本人

ml_user_favorites / ml_browse_history / ml_user_coupons

  • Customer
    • SELECT/INSERT/UPDATE/DELETE:仅本人

ml_orders

  • Customer
    • SELECT/INSERT/UPDATE/DELETE:仅自己的订单
  • Merchant
    • SELECT/INSERT/UPDATE/DELETE:仅 merchant_id 为自己的订单
  • Admin
    • 建议service role 或独立策略全量访问

ml_products

  • Public / Customer
    • SELECT:仅上架(status=1
  • Merchant
    • SELECT:至少能看上架;更合理的做法是:商家能看自己所有状态商品(当前策略是否支持需核对)
    • INSERT/UPDATE/DELETE:仅自己的商品

5. 关键前提与性能建议

5.1 ak_users.auth_id 的唯一性与索引

由于策略频繁执行子查询:

select auth_id from ak_users where id = ...

建议:

  • 确保 ak_users.id 为主键(已有)
  • 确保 ak_users.auth_id 存在且唯一(建议唯一索引)

5.2 RLS 子查询的成本

RLS 每次查询都要执行策略表达式。若策略中大量子查询,可能带来性能压力。

可选优化方向:

  • 在业务表冗余 auth_id(空间换性能)
  • 使用 security definer 函数封装策略逻辑(需谨慎)
  • 确保常用过滤字段(user_id/merchant_id/status)有索引