我正在用 Ruby on Rails 构建一个 JSON API。我想要只写用户帐户,这些帐户应该向系统提供数据但不允许从中读取数据。
为了实现额外的安全层,我想在数据库级别强制执行此规则。
想法是拥有一个“writer”类型的用户,它使用一个单独的数据库连接。应该允许此连接插入/更新/删除但不允许选择。
我已经很好地设置了一切,但不幸的是 Rails 在插入时生成了这个查询:
INSERT INTO "default"."products" ("id", "name", "sku") VALUES ($1, $2, $3) RETURNING "id"
“RETURNING id”部分导致失败,因为用户没有 SELECT 权限:
ActiveRecord::StatementInvalid: PG::InsufficientPrivilege: ERROR: permission denied
for relation products:
INSERT INTO "default"."products" ("id", "name", "sku") VALUES ($1, $2, $3) RETURNING "id"
有什么方法可以在 PG 或 Rails 中解决这个问题?我看到的两个选项是:
- 在 PG 中向 writer 用户授予“有限的”SELECT 权限,因此他们只能“查看”某些列。我完全不知道这是否可能。
- 让 Rails 在查询末尾不添加“RETURNING id”,尽管这可能会产生副作用。
我找到了一篇文章,有人遇到了同样的问题,最后只是向作者用户授予了 SELECT 权限:
https://til.hashrocket.com/posts/0c83645c03-postgres-permissions-to-insert-but-not-return
有没有可能有一个实际的解决方案来让上面的设置工作?
最佳答案
自 PostgreSQL 9.5 以来,有一种使用行级安全功能的方法:
create table products(id serial primary key, name text not null, sku text not null);
grant select,insert on products to tometzky;
grant usage on sequence products_id_seq to tometzky;
alter table products enable row level security;
create policy products_tometzky on products to tometzky
using (id=currval('products_id_seq'));
tometzky=> select * from products;
ERROR: currval of sequence "products_id_seq" is not yet defined in this session
tometzky=> insert into products (name, sku) values ('a','a') returning id;
1
tometzky=> select * from products;
1|a|a
tometzky=> insert into products (name, sku) values ('b','b') returning id;
2
tometzky=> select * from products;
2|b|b
用户只能看到他放入数据库的最后一行。反正他知道那是什么。
关于ruby-on-rails - PostgreSQL + rails : is it possible to have a write-only database user in PG?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43641326/