我需要严格控制Postgres数据的读写.可更新视图始终提供非常好,严格的数据读取控制,并允许我添加有价值的计算列.使用Postgres 9.5行级安全性引入了一种新的强大的方法来控制我的数据.但我不能同时使用两种技术视图和行级安全性.为什么?
是否有内置功能,或在Oracle中找到的SQL Server 2008中模拟RLS(行级安全性)的方法?
我想要掌握在支持Web应用程序的多租户数据库中使用新行级安全功能的最佳方法.
目前,该应用程序有几个不同的ROLE可用,具体取决于它尝试采取的操作.
一旦应用程序使用自己的ROLE建立连接,应用程序就会将身份验证参数(由用户提供)传递到不同的函数中,这些函数根据用户提供的身份验证参数筛选出行.该系统旨在与成千上万的用户合作,它似乎工作; 然而,它是狡猾的(而且很慢).
似乎如果我想使用新的行级安全功能,我需要为每个真实世界用户(不仅仅是Web应用程序)创建一个新的ROLE来访问数据库.
它是否正确?如果是这样,在数据库中创建数千个ROLE是一个好主意吗?
从评论中的a_horse_with_no_name链接更新(谢谢,该线程是正确的):
CREATE USER application;
CREATE TABLE t1 (id int primary key, f1 text, app_user text);
INSERT INTO t1 VALUES(1,'a','bob');
INSERT INTO t1 VALUES(2,'b','alice');
ALTER TABLE t1 ENABLE ROW LEVEL SECURITY;
CREATE POLICY P ON t1 USING (app_user = current_setting('app_name.app_user'));
GRANT SELECT ON t1 TO application;
SET SESSION AUTHORIZATION application;
SET app_name.app_user = 'bob';
SELECT * FROM t1;
id | f1 | app_user
----+----+----------
1 | a | bob
(1 row) …Run Code Online (Sandbox Code Playgroud) 我一直在考虑如何使用实体框架实现行级安全性.我们的想法是拥有一个数据库不可知的方法,它将提供限制来自ObjectContext的行的方法.
我的一些初步想法涉及修改EDMGEN工具创建的部分类,并提供了一些有限的支持.用户仍然可以使用自己的eSQL语句和QueryObject来解决此问题.
我一直在寻找一种全面的解决方案,它将存在于数据库提供商之上,以便它仍然是不可知的.
信息软件中一个非常重要的问题是具有不同职责和访问级别的不同角色的用户的存在.例如,想象一下具有如下结构(层次结构)的组织:
[Organization Role ] [Organization ID]
CEO org01
Financial Assistant org0101
personnel 1
Software Assistant org0102
personnel 2
Commercial Assistant org0103
personnel 3
Run Code Online (Sandbox Code Playgroud)
想象一下,该组织有一个管理人员信息的系统.在该系统中显示人员信息的规则是每个用户都可以看到他有权访问的组织的人员信息; 例如,'user1'可以访问'财务助理'和'商务助理'级别,因此他只能看到'人员1'和'人员3'的信息.同样,'user2'只能访问'Commercial Assistant'级别,因此他只能看到'人员3'的信息.因此,该系统中的每个用户都具有特定的访问级别.现在考虑在这个系统中,每个用户只能看到他登录后可以访问的人员信息.具有这个系统的表结构是这样的:
[Organization]
id
code
name
[Employee]
id
first_name
last_name
organization_id
[User]
id
user_name
password
[UserOrganization]
user_id
organization_id
Run Code Online (Sandbox Code Playgroud)
以下查询足以获得每个用户的正确人事信息结果:
select *
from employee e
where e.organization_id in
(select uo.organization_id
from user_organization uo
where uo.user_id=:authenticatedUserId)
Run Code Online (Sandbox Code Playgroud)
我们可以看到,以下条件定义了显示正确数据的访问逻辑:
e.organization_id in
(select uo.organization_id
from user_organization uo
where uo.user_id=:authenticatedUserId)
Run Code Online (Sandbox Code Playgroud)
这种访问级别也称为"行级安全性"(RLS).另一方面,相应的存储库类可能有几个负责读取数据的方法,所有这些方法都必须满足适当的访问级别条件.在这种情况下,访问级别条件将在某些地方(方法)重复.似乎使用'休眠过滤器'将是解决此问题的正确方法.唯一需要的是一个过滤器,它获取经过身份验证的用户的id,并在每个读取方法之前执行'enablefilter'命令.
@Filters( {
@Filter(name=“EmployeeAuthorize", condition="(organization_id in (select uo.organization_id from user_organization uo where …Run Code Online (Sandbox Code Playgroud) spring hibernate row-level-security spring-security spring-data
我目前正在评估身份验证/授权框架.
Apache Shiro似乎非常好,但我缺少行级安全功能.
例如,数据库中可能存在特殊行,只有具有特殊权限的用户才能看到和访问这些行.为避免不必要的往返,我们目前修改SQL查询以与我们的授权数据连接,以仅获取当前用户的可见行.
但是这个概念对我来说并不合适,因为我们将业务代码与安全相关的代码混合在一起,这些代码应该是正交的并且彼此独立.
更新:
目标数据库主要是Oracle 10g/11g
- 但如果没有大的缺点,则首选独立于数据库的解决方案
我正在使用PostgreSQL 10.1,直奔主题...
假设我有一个TABLE:
CREATE TABLE public.document (
id uuid PRIMARY KEY,
title text,
content text NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
连同上面的GIN INDEX:
CREATE INDEX document_idx ON public.document USING GIN(
to_tsvector(
'english',
content || ' ' || COALESCE(title, '')
)
);
Run Code Online (Sandbox Code Playgroud)
还有一个基本的全文搜索查询:
SELECT * FROM public.document WHERE (
to_tsvector(
'english',
content || ' ' || COALESCE(title, '')
) @@ plainto_tsquery('english', fulltext_search_documents.search_text)
)
Run Code Online (Sandbox Code Playgroud)
无论public.document表大小如何,查询都非常快(您已经知道了)!规划器使用 INDEX,一切都很好。
现在我通过RLS (Row Level Security)介绍一些基本的访问控制,首先我启用它:
ALTER TABLE public.document ENABLE ROW …Run Code Online (Sandbox Code Playgroud) 首先,这个SO问题描述了一个类似的问题:PostgreSQL query not using INDEX when RLS (Row Level Security) isenabled ,但我无法成功利用它的建议,还想看看是否有改进的方法Postgraphile 背景下的事物。
复制步骤:
作为超级用户,创建一个简单的表并用一些随机数据填充它:
CREATE TABLE public.videos AS SELECT id, md5(random()::text) AS title from generate_Series(1,1000000) id;
Run Code Online (Sandbox Code Playgroud)
执行 ILIKE 查询(在本文中,它被称为“ILIKE 查询”,用于多次测试性能):
EXPLAIN ANALYSE SELECT COUNT(*) FROM public.videos WHERE title ILIKE '%test%';
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,它执行了 Seq Scan,执行时间约为 194.823 ms
安装 gp_trgm 扩展并添加 gin 索引:
CREATE EXTENSION IF NOT EXISTS pg_trgm WITH SCHEMA public;
CREATE INDEX trgm_idx_videos_title ON public.videos USING gin (title gin_trgm_ops);
Run Code Online (Sandbox Code Playgroud)
由于表已经填充了数据,因此创建索引需要一些时间(约 10 秒)。现在,运行相同的 ILIKE 查询将使用“trgm_idx_videos_title 上的位图索引扫描”,执行时间为 0.036 毫秒。
到目前为止一切似乎都很好,但前提是您可以始终使用超级用户来获取数据并且不为所述表实现额外的安全性。
让我们设置一个额外的用户并授予其连接到我们的数据库的权限(名为 …
postgresql indexing performance row-level-security postgraphile
我有基于 postgres (13.2) 的 API,启用了 RLS(我使用 postgraphile),而且速度非常慢。用户从 Google OAuth 发送 JWT。对表的访问基于角色(有 2 个:人员、管理员)+ RLS。我有 2 个用户身份验证表:person、person_groups
CREATE TABLE IF NOT EXISTS myschema.person_groups (
id serial PRIMARY KEY,
person_id citext NOT NULL REFERENCES myschema.person (id),
google_id text NOT NULL REFERENCES myschema_private.person_account (google_id),
group_id serial NOT NULL REFERENCES myschema.groups (id),
updated_at timestamp DEFAULT now(),
CONSTRAINT unq_person_id_group_id UNIQUE (person_id, group_id)
);
CREATE INDEX persongroups_google_group_idx ON myschema.person_groups (google_id, group_id);
Run Code Online (Sandbox Code Playgroud)
为了进行 RLS 检查,我将函数指定为:
CREATE OR REPLACE FUNCTION myschema.is_in_group (group_id int[])
RETURNS boolean
AS $$
SELECT …Run Code Online (Sandbox Code Playgroud) postgresql ×5
sql ×3
database ×2
security ×2
sql-server ×2
c# ×1
hibernate ×1
indexing ×1
java ×1
performance ×1
postgraphile ×1
shiro ×1
spring ×1
spring-data ×1
views ×1