You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何结合行级安全与列权限实现用户数据访问控制?

这是一个典型的PostgreSQL行级安全(RLS)应用场景,我帮你一步步拆解实现步骤,确保每个角色的权限完全符合需求:

1. 准备角色(如果不存在的话)

postgres默认是超级用户,一般已经存在,我们只需要创建另外两个角色:

-- 创建认证用户角色(NOLOGIN表示不能直接登录,通常应用用户会继承这个角色)
CREATE ROLE authenticated_user NOLOGIN;
-- 创建访客角色
CREATE ROLE visitor NOLOGIN;

-- 补充:如果需要让具体用户登录,可以创建带LOGIN的用户并继承角色
-- 比如创建一个名为alice的认证用户:
-- CREATE USER alice WITH PASSWORD 'your_secure_password';
-- GRANT authenticated_user TO alice;
2. 创建users表

必须添加user_id列,用来关联当前登录用户,这是实现“仅访问自身private_data”的核心依据:

CREATE TABLE users (
    user_id TEXT PRIMARY KEY, -- 建议和角色/用户名保持一致,方便关联
    public_data TEXT NOT NULL,
    private_data TEXT NOT NULL,
    system_data TEXT NOT NULL
);
3. 重置基础权限

首先撤销public角色对users表的默认权限,避免不必要的访问:

REVOKE ALL ON TABLE users FROM public;

然后给postgres授予全权限(超级用户本来就有,这里明确配置更清晰):

GRANT ALL ON TABLE users TO postgres;
4. 配置行级安全(RLS)策略

这是实现细粒度权限控制的核心,先开启users表的RLS:

ALTER TABLE users ENABLE ROW LEVEL SECURITY;

4.1 访客(visitor)权限策略

访客只能读取所有用户的public_data

-- 授予访客仅读取public_data列的权限
GRANT SELECT (public_data) ON TABLE users TO visitor;
-- 允许访客访问所有行(因为要看到所有用户的public_data)
CREATE POLICY visitor_access_policy ON users
    FOR SELECT TO visitor
    USING (true);

4.2 认证用户(authenticated_user)权限策略

认证用户可以读取所有用户的public_data,仅能读取自身的private_data,无法访问system_data

-- 授予认证用户读取public_data和private_data列的权限
GRANT SELECT (public_data, private_data) ON TABLE users TO authenticated_user;

-- 策略1:允许认证用户访问所有行的public_data
CREATE POLICY authenticated_public_access ON users
    FOR SELECT TO authenticated_user
    USING (true);

-- 策略2:仅允许认证用户访问自身行的private_data
CREATE POLICY authenticated_private_access ON users
    FOR SELECT TO authenticated_user
    USING (user_id = current_user);

这里的逻辑是:当认证用户查询public_data时,所有行都可见;当查询private_data时,只有user_id等于当前登录用户的行才会被返回。

5. 验证权限配置

可以通过切换角色来测试每个角色的权限是否符合预期:

-- 测试访客角色
SET ROLE visitor;
-- 可以正常读取所有public_data
SELECT public_data FROM users;
-- 尝试读取private_data或system_data会报错(权限不足)
SELECT private_data FROM users; -- 报错:permission denied for table users

-- 测试认证用户角色(假设已创建alice用户并继承authenticated_user)
SET ROLE alice;
-- 可以读取所有用户的public_data
SELECT public_data FROM users;
-- 只能读取自己的private_data
SELECT private_data FROM users WHERE user_id = 'alice'; -- 返回数据
SELECT private_data FROM users WHERE user_id != 'alice'; -- 返回空结果
-- 尝试读取system_data报错
SELECT system_data FROM users; -- 报错:permission denied for table users

-- 测试超级用户postgres
SET ROLE postgres;
-- 可以读取所有列所有行
SELECT * FROM users;

内容的提问来源于stack exchange,提问作者Julien

火山引擎 最新活动