初探supabase: RLS、trigger、edge function

supabase是什么?

一个BaaS,在postgres上增加api层,为每个表生成api。并且支持 edge function(serverless函数调用),storage (对象存储),认证等

管理项目

创建一个Project,填写基本信息,包括数据库密码,选择Region

创建好之后,到首页可以看到一个URL和API KEY,前端将通过他来调用 supabase的提供的data api对数据库进行增删改查。

下面的小字说,这个key是可以被公开的,那么supabase是如何确保数据库操作的安全呢?答案是通过RLS实现的行级别的鉴权,这个后面会说到。

认证

supabase提供了开箱即用的认证功能,可以不写一行代码实现用户注册、登录等。

到 API docs -- User Managerment可以看到如何用去注册一个用户

我们命令行复制 并执行:

发现api成功返回了,然后到Table Editor中auth.users中可以看到,多了一条用户记录

这里schema有多种,其中auth是supabase直接管理的,用来实现认证,用户不能进行修改

用户创建的表在public下,创建完之后 supabase 会自动生成增删改查的api

建表

从上一部分可以看到,auth.users 并不存在 用户名称、简介等业务信息,就需要我们自己在public下创建一个users表,然后使用外键建立关联

设置外键,将public.users.uid 指向 auth.users.id ,并且设置当 auth.users记录被删除时,同步删除业务表的记录

trigger function

现在发现了个问题,当用户注册的时候,auth.users 会多一条记录,但是public.users却没有,难道还需要我们登录之后手动调用insert创建吗?

其实不用,我们可以使用supabase的trigger function,auth.users改变时触发,执行sql给public.users插入一条记录

到 Database -> function, 在public创建一个function,其实就是执行了一段sql,其中 new 代表auth.users中的一条记录,raw_user_meta_data 则是调用接口时传入的业务对象,这个现在看起来有点懵逼,后面会说到

sql 复制代码
-- 创建函数
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.users (uid, username)
  VALUES (
    NEW.id,
    NEW.raw_user_meta_data->>'username',
  );
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

有了执行逻辑,还要定义什么时候触发,到database -> triggers, 在public下新增一个trigger,指定到auth.users表插入的时候执行对应的trigger:

sql 复制代码
-- 创建触发器
CREATE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();

然后删除刚刚的数据,

sql 复制代码
delete from auth.users where id = '06ca9840-a63f-447e-96af-e7f3ff768342'

重新注册一下,注意这里data对象就是上面函数中的raw_user_meta_data:

再查看一下业务表 public.users,多了一条记录

RLS: Row Level Security

如果想对某些行进行鉴权,比如

  1. 用户只能修改自己的信息
  2. 任何人都可以创建post
  3. 任何人只能查看自己的post

就需要用到RLS,通过创建polices来控制,官方的例子很具体了,这里解释一下

vbnet 复制代码
create policy "Public profiles are viewable only by authenticated users"
on profiles for select
to authenticated
using ( true );

表示创建了一个规则,对于profiles的select操作,对登录用户进行限制,限制为true,就是任何登录用户都可以查看profiles

sql 复制代码
create policy "Users can update their own profile."
on profiles for update
to authenticated -- the Postgres Role (recommended)
using ( (select auth.uid()) = user_id ) -- checks if the existing row complies with the policy expression
with check ( (select auth.uid()) = user_id ); -- checks if the new row complies with the policy expression

这里 auth.uid() 是从读取请求中的jwt解析得到的人当前登录用户的id,user_id是表中的列

这个polices限制了,对于profile的更新操作,只有登录用户,可以查看到自己的(using),并且修改后id不能变(with check),没有with check的话,用户可以把自己的profile中的uid改成别人的

这里区分一下using和with check的区别:

逻辑 含义
USING 能不能选中这行(决定可操作范围)
WITH CHECK 改完后是否合法(防止越权写入)

待补充

相关推荐
linux_cfan37 分钟前
17 · 引擎适配器全景:HLS/DASH/Vimeo/Mux/Cast
前端·javascript·音视频
计算机魔术师1 小时前
烧掉2780亿美元还不够?OpenAI的资本豪赌让人头皮发麻
前端
IT_陈寒2 小时前
Java线程池用错参数,我的服务居然悄悄崩溃了
前端·人工智能·后端
卡布鲁2 小时前
React useMemo 与 useCallback 完全指南:原理、场景与避坑
前端·react.js
碳基修炼2 小时前
排查记:本地 devServer 是 http,浏览器却把 302 重定向升级成了 https
前端·http
步行cgn2 小时前
Spring p 命名空间注入详解
java·前端·spring
何何____3 小时前
Vue 生命周期详解
前端·javascript
江米小枣tonylua3 小时前
TypeScript 全面の拥抱 !Prisma 8 + Electron 升级实战
前端
闪耀之光M783 小时前
npm命令解析
前端
咸鱼老弟3 小时前
AI Agent 的"自主性悖论"——为什么给它的自由度越大,越要配一套更硬的护栏
前端·人工智能