关于
了解如何通过启用行级安全和在MemFire Cloud仪表板中编写策略来限制对数据库表的访问。
确保你的表的安全
在MemFire Cloud中,你可以直接从客户端(通常是网络浏览器)访问你的数据,你可以通过将你的MemFire Cloud URL和Anon密钥传递给supabase-js来做到这一点。
const supabase = createClient(
'https://qwertyuiop.supabase.co',
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c'
)
然而,这引起了一个有趣的问题:"如果我的匿名密钥在客户端,那么就不会有人阅读我的javascript并窃取我的密钥吗?",答案是肯定的。而这正是Postgres策略的作用所在。
使用Postgres的 "行级安全 "策略,我们可以设置规则,允许或不允许匿名钥匙在默认情况下访问哪些数据。
例如,我们可以说匿名钥匙只能从一个特定的表中读取,但不能写入、更新或删除。
而且这些规则可以随我们的意愿而复杂。我们可以说,匿名键只能删除在星期四下午4点到6点之间插入的记录,并且id列是偶数。很奇怪,但它显示了策略的力量。
比方说,我们创建了一个排行榜表。我们希望网站上的人能够阅读排行榜,但不能写入、更新或删除它。我们首先在SQL中定义我们的表并添加一些假数据。
create table leaderboard (
name text,
score int
);
insert into leaderboard(name, score)
values ('Paul', 100), ('Leto', 50), ('Chani', 200);
现在让我们设置一个客户端来读取数据,我在这里创建了一个副本来展示一个活生生的例子。https://replit.com/@awalias/supabase-leaderboard-demo#index.js。如果你复制这个片段,你可以插入你自己的Supabase URL和anon key。
你可以看到,通过使用,可以自由地从表中读取和写入。
// Writing
let { data, error } = await supabase.from('leaderboard').insert({ name: 'Bob', score: 99999 })
// Reading
let { data, error } = await supabase
.from('leaderboard')
.select('name, score')
.order('score', { ascending: false })
现在我们来限制访问。我们将从完全限制该表开始。我们可以在SQL编辑器中通过做一个查询来做到这一点:
ALTER TABLE leaderboard ENABLE ROW LEVEL SECURITY;
或通过MemFire Cloud 仪表板,导航至 数据库 > 权限设置,并单击"启用 RLS"按钮,开启RLS。
你会注意到,现在读和写都失败了,出现了类似的错误。
{
hint: null,
details: null,
code: '42501',
message: 'new row violates row-level security policy for table "leaderboard"'
}
现在我们需要添加一个策略,使每个在 Authorization: Bearer
头 中发送匿名密钥(JWT)的人能够读取该表。
在SQL中,这可以通过以下方式完成:
CREATE POLICY anon_read_leaderboard ON leaderboard
FOR SELECT
USING (auth.role() = 'anon');
anon_read_leaderboard
这里只是你为你的策略选择的一个名字。leaderboard
是表的名称。FOR SELECT
表示我们只希望这个策略适用于读取(或者说SQL中的 "选择")。最后,规则本身是auth.role() = 'anon'
。
auth.role()
是指一个SQL函数role
,MemFire Cloud将其注入你的数据库中的auth
模式。该函数实际上看起来像这样。
-- Gets the User Role from the request cookie
create or replace function auth.role() returns text as $$
select nullif(current_setting('request.jwt.claim.role', true), '')::text;
$$ language sql stable;
该函数的目的是从通过Authorization:Bearer
头传递给API的任何JWT中提取role
声明。
其他可在此使用的函数包括:auth.email()
和auth.uid()
,它们将分别获取email
和sub
的声明。
如果你愿意使用仪表板来添加你的策略,你可以通过点击策略标签中的 "添加策略 "来完成,并制作一个类似这样的策略。
你现在应该可以从你的排行榜上读取信息,但仍然不能写入、更新或删除,这正是我们想要的!
快速提醒你,你总是可以使用你的service_role
API密钥来绕过这些行级安全策略。但是要格外小心,不要把这个密钥包含在客户端中,以免泄露。如果你正在建立内部管理工具,或者你需要通过API批量插入或删除数据,这可能很有用。
在下一篇指南中,我们将探讨如何将策略与用户账户结合起来使用,这样你就可以在用户的基础上限制对数据的访问。观看第三部分:策略
资源
- JWT debugger: https://jwt.io/
- RESTED: https://github.com/RESTEDClient/RESTED
接下来的步骤
- 第一部分: JWTs
- 第三部分:策略
- 第四部分:GoTrue
- 注册MemFire Cloud:MemFire Cloud