4.4 KiB
4.4 KiB
05 RLS 权限矩阵(Supabase 行级安全)
本节整理 complete_mall_database.sql 中的 RLS(Row 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_profilesml_user_addressesml_shopping_cartml_user_favoritesml_browse_historyml_user_couponsml_ordersml_products
备注:其他表(如
ml_categories/ml_brands/ml_shops/ml_order_items等)在该脚本片段中未显式启用 RLS。
3. 核心策略模式(pattern)
3.1 “归属自己”的通用模式
对用户私有表(档案、地址、购物车、收藏、浏览、券)使用类似逻辑:
SELECT/UPDATE/DELETE:要求当前auth.uid()对应到该行的user_idINSERT:要求插入行的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_id 或 merchant_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为自己的订单
- SELECT/INSERT/UPDATE/DELETE:仅
- Admin
- 建议:service role 或独立策略全量访问
ml_products
- Public / Customer
- SELECT:仅上架(
status=1)
- SELECT:仅上架(
- 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)有索引