6个必须掌握的Supabase技巧

Supabase 是一个开源的后端即服务(BaaS),提供了一个 PostgreSQL 数据库、认证、存储 和 实时 API。

6个必须掌握的Supabase技巧

Supabase 是一个开源的后端即服务(BaaS),提供了一个 PostgreSQL 数据库认证存储实时 API——所有这些都可以通过 RESTful 或 GraphQL 接口立即使用。它旨在帮助开发者构建可扩展的 Web 和移动应用程序,而无需管理基础设施。

1、分离服务器和客户端上下文

一个常见的错误是误用 Supabase 密钥并在客户端暴露敏感访问权限。Supabase 提供了两种类型的密钥:anon(公开)和 service_role(私有)。始终将 service_role 密钥保留在服务器端。

客户端连接(浏览器安全):

import { createClient } from '@supabase/supabase-js';  

const supabase = createClient(  
  process.env.NEXT_PUBLIC_SUPABASE_URL!,  
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!  
);

服务器端连接(管理员权限):

import { createClient } from '@supabase/supabase-js';  

const supabaseAdmin = createClient(  
  process.env.SUPABASE_URL!,  
  process.env.SUPABASE_SERVICE_ROLE_KEY!  
);

避免在前端使用 service_role 密钥,因为它会绕过所有的行级安全性,并且如果泄露会导致整个数据库被泄露。

2、与 Drizzle ORM 集成以实现类型安全

Drizzle ORM 是 TypeScript 的一个功能强大的、类型安全的 SQL 查询生成器。在使用 Supabase 时,你可以直接通过连接字符串将 Drizzle 连接到你的 PostgreSQL 实例。

示例设置:

import postgres from 'postgres';  
import { drizzle } from 'drizzle-orm/postgres-js';  

const client = postgres(process.env.SUPABASE_DB_URL); // 例如:'postgres://user:password@host:5432/db'  
export const db = drizzle(client);

显式定义你的模式:

import { pgTable, serial, varchar, timestamp } from 'drizzle-orm/pg-core';  

export const users = pgTable('users', {  
  id: serial('id').primaryKey(),  
  email: varchar('email', { length: 255 }).notNull(),  
  createdAt: timestamp('created_at').defaultNow()  
});

Drizzle 可以完全控制你的模式、迁移和查询,同时提供静态类型安全,而没有运行时开销。

3. 使用 Supabase 策略强制实施行级安全性

Supabase 利用了 PostgreSQL 的原生行级安全性(RLS)来限制对数据的行级访问。启用和配置 RLS 对构建安全的多用户应用程序至关重要。

启用 RLS:

ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;

创建策略:

CREATE POLICY "Users can access their profile"  
ON profiles  
FOR SELECT USING (auth.uid() = id);

这些策略依赖于 auth.uid() 函数,该函数返回当前已认证用户的 ID。当正确配置时,你可以在前端安全地使用 Supabase 客户端,而不会泄露跨用户的数据。

4、使用边缘函数进行安全的业务逻辑和后台任务

Supabase 边缘函数允许你使用 Deno 安全地运行服务器端代码。这对于发送电子邮件、验证 webhook 签名或处理由 Supabase Realtime 或数据库更改触发的事件非常有用。

示例:发送事务性电子邮件

// sendWelcomeEmail.ts  
import { serve } from "https://deno.land/std/http/server.ts";  

serve(async (req) => {  
  const { email } = await req.json();  
  // 在这里使用 Resend 或 Mailgun 等提供商发送电子邮件逻辑  
  return new Response(JSON.stringify({ status: "sent" }), { status: 200 });  
});

部署命令:

supabase functions deploy sendWelcomeEmail

边缘函数靠近用户运行,集成了 Supabase Auth 和 Storage,并且内置了对密钥和访问控制的支持。

5、Supabase 存储:签名 URL 和访问控制

Supabase 存储基于 S3 兼容的对象存储构建。它允许你存储文件并使用 RLS 和签名 URL 控制访问。

上传文件:

const { data, error } = await supabase.storage  
  .from('avatars')  
  .upload('user123/avatar.png', file);

生成签名 URL(例如用于私人下载):

const { data } = await supabase.storage  
  .from('avatars')  
  .createSignedUrl('user123/avatar.png', 60); // 有效期为 60 秒

文件的访问受策略控制,就像数据库行一样。例如,你可以使用 RLS 限制下载到文件所有者。

6、将 Drizzle ORM 与 Supabase Auth 用户连接

当你使用 Supabase Auth 时,用户 ID 以 UUID 的形式存储。为了使用 Drizzle 将其与自己的应用表关联,请正确声明外键。

import { uuid } from 'drizzle-orm/pg-core';  

export const profiles = pgTable('profiles', {  
  id: uuid('id').primaryKey(), // 匹配 Supabase Auth UID  
  fullName: varchar('full_name', { length: 100 }),  
});

这确保了你的用户表与身份验证系统对齐,并强制执行适当的引用完整性。


原文链接:5 Must Known Supabase Tricks for Every Developer

汇智网翻译整理,转载请标明出处