认证
用户管理
MemFire Cloud采用Supabase的认证服务,让管理应用用户变得更简单。
当用户注册时,系统为他们分配了一个唯一的 ID。你可以在你的数据库中的任何地方引用这个ID。例如,你可以创建一个profiles
表,使用user_id
字段引用用户。
supabase 提供了注册、登录、退出的接口,并在你的应用程序和网站中管理用户。
行级安全
身份验证只能让你做到这一点。当你需要细化的授权规则时,没有什么比PostgreSQL的行级安全(RLS)更好的了。 supabase 使得打开和关闭RLS变得很简单。
策略
策略是PostgreSQL的规则引擎。它们非常强大和灵活,允许你编写复杂的SQL规则,以适应你独特的业务需求。
有了策略,你的数据库就成了规则引擎。而不是重复地过滤你的查询,像这样...
... 您只需在数据库表上定义一个规则,auth.uid()= user_id
,即使从中间件中删除筛选器,您的请求也将返回通过该规则的行:
策略就像where条款
一旦你掌握了这些策略,就很容易理解。你可以把它们看作是在每个查询中添加一个WHERE
子句。例如,如果你有一个这样的策略:
create policy "Individuals can view their own todos." on todos for
select using (auth.uid() = user_id);
每当用户试图从todos表中选择时,它就会转化为这样:
select *
from todos
where auth.uid() = todos.user_id; -- Policy is implicitly added.
工作原理
- 用户注册。supabase在“auth.users”表中创建一个新用户。
- supabase返回一个新的JWT,其中包含用户的“UUID”。
- 对数据库的每个请求都会发送JWT。
- MemFireDB检查JWT以确定提出请求的用户。
- 可以在策略中使用用户的UID来限制对行的访问。
MemFire Cloud在MemFireDB中提供了一个特殊的函数,auth.uid()
,它从JWT中提取用户的uid。这在创建策略时特别有用。
策略实例
下面是一些示例,向您展示PostgreSQL的RLS的强大功能。每个策略都附加到一个表,并且每次访问表时都会执行该策略。
允许读访问
-- 1. Create table
create table profiles (
id uuid references auth.users,
avatar_url text
);
-- 2. Enable RLS
alter table profiles
enable row level security;
-- 3. Create Policy
create policy "Public profiles are viewable by everyone."
on profiles for select using (
true
);
- 在公共模式(默认模式)中创建一个名为
profiles
的表。 - 启用行级安全。
- 创建一个策略,允许运行所有select查询。
限制更新
-- 1. Create table
create table profiles (
id uuid references auth.users,
avatar_url text
);
-- 2. Enable RLS
alter table profiles
enable row level security;
-- 3. Create Policy
create policy "Users can update their own profiles."
on profiles for update using (
auth.uid() = id
);
- 在公共模式(默认模式)中创建一个名为
profiles
的表。 - 启用RLS。
- 创建一个策略,允许登录的用户更新他们自己的数据。
带连接的策略
策略甚至可以包括表的连接。这个例子显示了你如何查询 外部
表以建立更高级的规则。
create table teams (
id serial primary key,
name text
);
-- 2. Create many to many join
create table members (
team_id bigint references teams,
user_id uuid references auth.users
);
-- 3. Enable RLS
alter table teams
enable row level security;
-- 4. Create Policy
create policy "Team members can update team details if they belong to the team."
on teams
for update using (
auth.uid() in (
select user_id from members
where team_id = id
)
);
具有安全定义函数的策略
策略还可以使用安全定义函数”
。这在要限制对链接表的访问的多对多关系中很有用。
在上面的teams
和members
示例之后,此示例演示了如何结合使用安全定义函数和策略来控制对members
表的访问。
-- 1. Follow example for 'Policies with joins' above
-- 2. Enable RLS
alter table members
enable row level security
-- 3. Create security definer function
create or replace function get_teams_for_user(user_id uuid)
returns setof bigint as $$
select team_id
from members
where user_id = $1
$$ stable language sql security definer;
-- 4. Create Policy
create policy "Team members can update team members if they belong to the team."
on members
for all using (
team_id in (
select get_teams_for_user(auth.uid())
)
);
验证电子邮件的域名
Postgres有一个函数right(string, n)
,可以返回一个字符串的最右边的n个字符。
你可以用它来匹配工作人员的电子邮件域名。
-- 1. Create table
create table leaderboard (
id uuid references auth.users,
high_score bigint
);
-- 2. Enable RLS
alter table leaderboard
enable row level security;
-- 3. Create Policy
create policy "Only Blizzard staff can update leaderboard"
on leaderboard
for update using (
right(auth.email(), 13) = '@blizzard.com'
);
数据的生存时间
策略也可以用来实现你在Instagram故事或Snapchat中看到的TTL或生存时间功能。
在下面的例子中,stories
表中的行只有在过去24小时内创建时才可用。
-- 1. Create table
create table if not exists stories (
id uuid not null primary key DEFAULT uuid_generate_v4(),
created_at timestamp with time zone default timezone('utc' :: text, now()) not null,
content text not null
);
-- 2. Enable RLS
alter table stories
enable row level security;
-- 3. Create Policy
create policy "Stories are live for a day"
on stories
for select using (
created_at > (current_timestamp - interval '1 day')
);
高级策略
使用SQL的全部功能来建立极其高级的规则。
在这个例子中,我们将创建一个posts
和comments
表,然后创建一个依赖于另一个策略的策略。
(在这个例子中,评论策略依赖于帖子策略)。)
create table posts (
id serial primary key,
creator_id uuid not null references auth.users(id),
title text not null,
body text not null,
publish_date date not null default now(),
audience uuid[] null -- many to many table omitted for brevity
);
create table comments (
id serial primary key,
post_id int not null references posts(id) on delete cascade,
user_id uuid not null references auth.users(id),
body text not null,
comment_date date not null default now()
);
create policy "Creator can see their own posts"
on posts
for select
using (
auth.uid() = posts.creator_id
);
create policy "Logged in users can see the posts if they belong to the post 'audience'."
on posts
for select
using (
auth.uid() = any (posts.audience)
);
create policy "Users can see all comments for posts they have access to."
on comments
for select
using (
exists (
select 1 from posts
where posts.id = comments.post_id
)
);
提示
你不需要使用策略
你也可以把你的授权规则放在你的中间件中,类似于你在其他 "后台<->中间件<->前端 "架构中创建安全规则的方式。
策略是一种工具。在 serverless/Jamstack
设置的情况下,它们特别有效,因为你根本不需要部署任何中间件。
然而,如果你想为你的应用程序使用另一种授权方法,这也是可以的。MemFire Cloud是单纯的Postgres
,所以如果你的应用程序可以使用Postgres,那么它也可以使用MemFire Cloud。
提示:确保为你的所有表启用RLS,这样你的表就无法访问了。然后使用我们提供的Service key
,这是为了绕过RLS。
检查MemFire Cloud上的认证设置
在 MemFire Cloud的"我的应用> 认证管理 > 认证设置",你就可以改变一些设置,比如。
- 网站网址,用于确定在用户确认其电子邮件地址或试图使用魔法链接登录后将其重定向到哪里。
- 禁用电子邮件确认功能。
不要在客户端使用服务密钥
MemFire Cloud 提供特殊的Service key
密钥,可用于绕过所有 RLS。
这些键不应该在浏览器中使用,也不应该暴露给客户,但它们对管理任务很有用。