You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中常规视图读取调用者视图的权限逻辑问询

PostgreSQL嵌套视图中security_invoker的角色切换逻辑解析

在PostgreSQL中,当常规视图嵌套调用security_invoker=true的视图时,角色权限的传递逻辑容易产生误解。本文结合测试场景解析其底层规则:

核心权限执行规则

  • 常规视图(未设置security_invoker):执行视图定义的查询时,会切换到视图所有者的角色权限,以此身份访问底层对象。
  • security_invoker=true的视图:执行视图定义的查询时,始终使用原始调用者的角色权限,不受任何上层视图的所有者身份影响——这是关键的规则差异。

测试场景验证

场景1:security_invoker视图调用常规视图

当带security_invoker=true的视图A查询常规视图B时:

  1. 视图A以调用者权限执行;
  2. 视图B作为常规视图,执行自身查询时切换到B的所有者权限,因此调用者看到的是B所有者权限下的内容,符合预期。

场景2:常规视图调用security_invoker视图

当常规视图C查询security_invoker=true的视图D时:

  1. 视图C执行时确实会切换到C的所有者权限;
  2. 但视图D是security_invoker=true,它会忽略上层的C所有者身份,直接使用原始调用者的权限执行自身查询,因此最终结果是调用者自身权限下的内容,而非C所有者权限——这就是与预期不符的原因。

测试代码

CREATE SCHEMA test_views;

SET search_path TO test_views;

CREATE ROLE emplo;
CREATE ROLE manager;
GRANT usage ON SCHEMA test_views TO emplo, manager;
GRANT CREATE ON SCHEMA test_views TO manager;

CREATE TABLE test_views.employees (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    department VARCHAR(100),
    salary NUMERIC
);

INSERT INTO test_views.employees (name, department, salary)
SELECT 
    'Employee ' || (RANDOM() * 100) :: INT,
    CASE
        WHEN RANDOM() < 0.5 THEN 'IT'
        ELSE 'HR'
    END,
    (RANDOM() * 100000) :: NUMERIC
FROM
    generate_series(1, 1000);


ALTER TABLE test_views.employees ENABLE ROW LEVEL SECURITY;

CREATE POLICY emplo_hr_policy ON test_views.employees 
FOR SELECT
USING (department = 'HR');

CREATE POLICY manager_all_policy ON test_views.employees 
FOR SELECT 
TO manager 
USING (TRUE);

GRANT INSERT ON test_views.employees TO manager;
GRANT SELECT ON test_views.employees TO emplo, manager;
GRANT usage ON SEQUENCE test_views."employees_id_seq" TO manager;
SET ROLE TO manager;

-- 创建带security_invoker的视图
CREATE OR REPLACE VIEW test_views.invoker_view WITH (security_invoker = TRUE) AS
SELECT *
FROM employees;

-- 创建调用invoker_view的常规视图
CREATE OR REPLACE VIEW test_views.leader_view AS
SELECT *
FROM invoker_view;

-- 创建常规视图
CREATE OR REPLACE VIEW test_views.normal_view AS
SELECT *
FROM employees;

-- 创建调用常规视图的security_invoker视图
CREATE OR REPLACE VIEW test_views.invoker_view_2 WITH (security_invoker = TRUE) AS
SELECT *
FROM normal_view;

GRANT SELECT ON 
    test_views.invoker_view,
    test_views.leader_view,
    test_views.normal_view,
    test_views.invoker_view_2 
TO emplo, manager;

测试查询与结果解析

select current_role;
set role to emplo;

select * from test_views.invoker_view; -- 以调用者emplo权限执行,仅看到HR部门数据
select * from test_views.leader_view; -- 常规视图leader_view切换到manager权限,但invoker_view强制使用原始调用者emplo权限,最终仅看到HR部门数据
select * from test_views.normal_view; -- 常规视图以所有者manager权限执行,看到所有部门数据
select * from test_views.invoker_view_2; -- invoker_view_2以调用者emplo权限执行,调用normal_view时切换到manager权限,最终看到所有部门数据

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:11:11