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

待补充

相关推荐
nwsuaf_huasir1 分钟前
积分旁瓣电平-matlab函数
前端·javascript·matlab
韭菜炒大葱11 分钟前
React Hooks :useRef、useState 与受控/非受控组件全解析
前端·react.js·前端框架
Cache技术分享15 分钟前
280. Java Stream API - Debugging Streams:如何调试 Java 流处理过程?
前端·后端
微爱帮监所写信寄信17 分钟前
微爱帮监狱寄信写信小程序信件内容实时保存技术方案
java·服务器·开发语言·前端·小程序
沛沛老爹18 分钟前
Web开发者实战A2A智能体交互协议:从Web API到AI Agent通信新范式
java·前端·人工智能·云原生·aigc·交互·发展趋势
这是个栗子24 分钟前
【Vue代码分析】vue方法的调用与命名问题
前端·javascript·vue.js·this
全栈前端老曹33 分钟前
【前端路由】Vue Router 动态导入与懒加载 - 使用 () => import(‘...‘) 实现按需加载组件
前端·javascript·vue.js·性能优化·spa·vue-router·懒加载
Zyx20071 小时前
构建现代 React 应用:从项目初始化到路由与数据获取
前端
大布布将军1 小时前
☁️ 自动化交付:CI/CD 流程与云端部署
运维·前端·程序人生·ci/cd·职场和发展·node.js·自动化
LYFlied1 小时前
Vue.js 中的 XSS 攻击防护机制详解
前端·vue.js·xss