MemFire教程|PostgreSQL RLS介绍

RLS(RowLevelSecurity)是数据库的行级安全特性,允许管理员设置访问策略以限制用户对特定数据的访问。在MemFireCloud中,RLS用于增强数据安全性,特别是在多租户应用中实现数据隔离。默认情况下RLS是关闭的,需要手动启用,并创建策略以定义用户访问权限。未配置策略时,RLS会阻止所有访问。RLS与GRANT命令结合使用,提供更细粒度的访问控制。文章通过示例展示了如何创建和管理RLS策略,以及其在多租户应用如todos管理中的应用。

前言

在使用MemFire Cloud的BaaS服务进行应用开发时,比较困扰开发者的是RLS的使用。本篇先从基本概念入手对RLS进行简要介绍,帮助大家理解RLS的工作机制和基本使用方法。

RLS是什么

全称:Row level security,行级安全,允许系统管理员为数据库表创建访问策略(policy),以约束数据的可见性。当为一个表创建了policy后,相当于为该表增加了一个高优先级的过滤器。当用户访问该表时,如果policy生效,则会根据policy中定义的过滤条件来决定用户可操作的数据集合。

如何开启RLS

RLS默认是不开启的,需要针对每个表执行如下语句来对该表开启RLS功能:

ALTER TABLE <name> ENABLE ROW LEVEL SECURITY

默认策略

当用户开启了RLS,但没有创建任何policy时,系统会启用默认策略。默认策略会拒绝用户访问该表中的任何数据。因此,在MemFire Cloud的应用中的表,如果启用RLS,至少要创建一条最简单的策略(如:允许任何人访问数据),否接口调试时会查询不到数据。

RLS 机制和 Grant指令有什么关系

grant是SQL标准语法,定义了一系列的数据访问权限的设置功能,比如允许用户对表执行查询操作,允许用户访问表中的哪些列。但是不能定义允许用户访问哪些行。

因此:RLS在某种程度上是对GRANT的一种补充,让用户能在行级别进行数据访问控制。

RLS不生效用户

RLS对三类用户不起作用:

  • superuser
  • owner
  • 添加了bypassrls权限的用户

举例:

create table photos(username text, pic text);
insert into photos values('zhangsan', '1.jpg'), ('lisi', '2.jpg');

create user zhangsan;
create user lisi;

grant select on table photos to zhangsan;
grant select on table photos to lisi;

-- 开启rls(没有创建policy的情况下,启用默认策略)
alter table photos ENABLE ROW LEVEL SECURITY;

-- 以memfire用户查询数据(superuser)
select * from photos;

-- 以zhangsan用户查询数据
set role  zhangsan;
select * from photos;

-- 将zhangsan设置为owner,再查询数据
set role memfire;
alter table photos owner to zhangsan;
set role zhangsan;
select * from photos;

-- 给lisi赋予bypassrls权限
alter user lisi with bypassrls;
set role lisi;
select * from photos;

如果想对owner也启用rls,语法如下:

ALTER TABLE ... FORCE ROW LEVEL SECURITY.

Policy 解释

policy是RLS使用的核心,用户需要对数据进行访问控制时,允许哪些用户在对哪些数据有什么操作权限,全部通过policy定义。

语法

CREATE POLICY name ON table_name
    [ AS { PERMISSIVE | RESTRICTIVE } ]
    [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]
    [ TO { role_name | PUBLIC | CURRENT_ROLE | CURRENT_USER | SESSION_USER } [, ...] ]
    [ USING ( using_expression ) ]
    [ WITH CHECK ( check_expression ) ]
  • name:同一个表上的policy不能重复,不同表的policy可以重复
  • table_name:为哪个表创建policy
  • AS,policy的生效模式,PERMISSIVE ,宽松模式,多个policy采用 or 进行组合判断,只要有一个policy过了就能访问数据;RESTRICTIVE,排他模式,必须满足的条件,当与其他policy组合使用时,使用 and 进行组合,只改条件不满足则其他条件再宽松也无用。默认PERMISSIVE 。
  • For,对哪个操作生效,默认ALL
  • TO,对哪个role生效,默认public
  • USING:对表中的已有数据进行检查的语句
  • WITH CHECK:对新数据进行检查的语句

举例

CREATE POLICY user_policy ON photos
    USING (username = current_user)
    with check(true);
    
 select * from photos where username = current_user;

多条policy的生效机制

CREATE POLICY user_sel_policy ON photos
    FOR SELECT
    USING (true);
CREATE POLICY user_mod_policy ON photos
    USING (user_name = current_user);

上面这两条policy,第一条只对select操作生效,第二条对select、update、insert、delete都生效。

  • 当执行select时,会用 or (PERMISSIVE )/ and(RESTRICTIVE )合并两个policy的条件。
  • 当执行update、insert、delete时,只有第二条policy生效。

RLS的应用场景

RLS在MemFire Cloud中的核心用途就是多租户数据隔离,以todos为例,对todos表按用户不同进行了最简单的权限控制,即:每个人只能创建、查看、修改、删除自己的数据,对其他人均不可见:

create table public.todos (
  id bigint generated by default as identity primary key,
  user_id uuid references auth.users not null,
  task text check (char_length(task) > 3),
  is_complete boolean default false,
  inserted_at timestamp with time zone default timezone('utc'::text, now()) not null
);
create index idx_todos_uid on public.todos (user_id);
alter table public.todos enable row level security;

create policy "个人只能创建自己的todos." on public.todos for
    insert with check (auth.uid() = user_id);

create policy "个人只能查看自己的todos. " on public.todos for
    select using (auth.uid() = user_id);

create policy "个人只能修改自己的todos." on public.todos for
    update using (auth.uid() = user_id);

create policy "个人只能删除自己的todos." on public.todos for
    delete using (auth.uid() = user_id);
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值