上篇文章我们已经了解了 Supabase Database 和 RLS 相关的内容,这篇文章我们集中在 Storage 这一块。Supabase 的 Storage 实际上用的是 AWS 的 对象存储,用于保存文件。但是使用 Supabase Storage 比直接使用对象存储要简单很多,特别是权限控制方面。Supabase Storage 复用了 RLS 的能力,直接通过 RLS 来控制权限。
文件上传和下载流程
如果直接使用 AWS 或者其它服务商的上传下载,传统的对象存储的上传流程是这样的:当用户需要上传或者下时,后端服务判断是否有上传或下载的权限,如果有,那么返回预签名地址,客户端通过预签名地址完成上传和下载逻辑。
而通过 Supabase Storage 上传或下载,那么只需要写入 RLS 策略到数据库中,在上传或下载时会自动判断用户是否有权限上传或下载。
两者的关键在于:前者需要开发一个后端服务接口来判断上传和下载权限并集成这个接口,而后者只需要只需要配置 RLS 策略。
那么原理是什么样子的呢?
Storage 权限控制的原理
原理上非常简单,对于所有的 Supabase Storage 文件,Supabase 有两张元数据表:storgae.buckets 和 storage.objects 用来存储对象存储的 bucket 和 object 的元数据。所以,对于对象存储的上传下载覆盖删除的权限,被 Supabase 映射为了对 storage.objects 表的 CRUD 的 RLS 。而对于 RLS ,我们在前篇已经学习了。
如何编写 storage RLS
要编写具体的 RLS,我们需要知道两个内容:谁可以访问什么文件?
而对于谁,和前篇一样,我们有两个信息供我们使用:role 和 auth.jwt()/auth.uid() 。 而对于可以访问什么文件,我们可以通过检查 Supabase 的 buckets 和 objects 表结构来检查可以使用的信息,通过在 Supabase 控制台的 Table Editor 选择 schema 为 storage 就可以看到相关的表结构了。
下面是一个官方示例: 用户只允许上传到 my_bucket_id,并且 path 为 /{users.id} 的 目录下。
create policy "Allow authenticated uploads"
on storage.objects
for insert
to authenticated
with check (
bucket_id = 'my_bucket_id' and
(storage.foldername(name))[1] = (select auth.jwt()->>'sub')
);