初探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 改完后是否合法(防止越权写入)

待补充

相关推荐
xiaotao1313 小时前
第九章:Vite API 参考手册
前端·vite·前端打包
午安~婉4 小时前
Electron桌面应用聊天(续)
前端·javascript·electron
彧翎Pro4 小时前
基于 RO1 noetic 配置 robosense Helios 32(速腾) & xsense mti 300
前端·jvm
小码哥_常4 小时前
解锁系统设置新姿势:Activity嵌入全解析
前端
之歆5 小时前
前端存储方案对比:Cookie-Session-LocalStorage-IndexedDB
前端
哟哟耶耶5 小时前
vue3-单文件组件css功能(:deep,:slotted,:global,useCssModule,v-bind)
前端·javascript·css
是罐装可乐5 小时前
深入理解“句柄(Handle)“:从浏览器安全到文件系统访问
前端·javascript·安全
华科易迅5 小时前
Vue如何集成封装Axios
前端·javascript·vue.js
康一夏5 小时前
Next.js 13变化有多大?
前端·react·nextjs
糖炒栗子03265 小时前
前端项目标准环境搭建与启动
前端