代码随想录算法训练营第四天 |24. 两两交换链表中的节点、19.删除链表的倒数第N个节点、面试题 02.07. 链表相交、142.环形链表II

核心内容摘要

Android Studio中文语言包配置指南:让开发环境说中文的完整方案
互联网大厂Java求职面试实战:核心技术与互联网医疗场景深度解析

无界办公新体验:wechat-need-web的网页化微信解决方案

文章目录

RLS 概述

1 RLS 基本原理

2 启用与配置 RLS

3 适用场景与局限

4 实践建议

实战案例场景1多租户 SaaS 应用

建表并启用 RLS

创建策略用户只能访问其租户的项目

应用层设置租户上下文

测试效果场景2员工只能查看自己的薪资

高级用法

1 不同操作使用不同条件

2 多策略组合

3 强制对表所有者生效

4 使用函数封装复杂逻辑

性能影响与优化

1 执行计划变化

2 索引建议

3 避免复杂函数

管理与调试

1 查看现有策略

2 临时禁用 RLS调试用

3 日志监控在 PostgreSQL 中行级安全Row-Level Security简称 RLS是一种强大的访问控制机制允许数据库管理员基于行数据的内容动态限制用户对表中特定行的 SELECT、INSERT、UPDATE 或 DELETE 操作。

RLS 使得多租户应用、数据隔离、隐私保护等场景无需在应用层硬编码过滤逻辑而是在数据库层实现细粒度安全控制。

本文将系统讲解 RLS 的原理、配置方法、使用场景、性能影响及最佳实践。

RLS 概述

1 RLS 基本原理PostgreSQL 的行级安全RLS提供了一种声明式、高效且安全的行过滤机制将数据访问控制下沉到数据库层显著降低应用复杂度并提升安全性。

通过合理设计策略、配合索引优化和会话上下文管理RLS 能够优雅支撑多租户、隐私合规等复杂业务需求。

关键原则启用 RLS → 定义策略 → 设置会话上下文 → 验证与监控。

默认情况下PostgreSQL 的权限控制是表级别的用户要么能访问整张表要么不能。

RLS 则在此基础上增加了一层行级别过滤当 RLS 启用后所有对该表的 DML 操作SELECT/INSERT/UPDATE/DELETE都会自动附加一个由策略定义的 WHERE 条件。

该条件基于当前用户、会话变量、行数据本身等上下文动态生成。

即使用户拥有表的 SELECT 权限若其操作不满足 RLS 策略相关行将被静默过滤不报错仅不可见。

注意超级用户superuser和表所有者table owner默认绕过 RLS。

可通过ALTER TABLE ... FORCE ROW LEVEL SECURITY强制对其生效。

2 启用与配置 RLS

启用 RLS-- 对表启用 RLS默认策略为“拒绝所有”除非定义了策略ALTERTABLEordersENABLEROWLEVELSECURITY;启用后若未定义任何策略则所有用户包括表所有者都无法访问该表超级用户除外。

创建安全策略使用CREATE POLICY定义访问规则。

语法如下CREATEPOLICY policy_nameONtable_name[FOR{ALL|SELECT|INSERT|UPDATE|DELETE}][TO{role_name|PUBLIC|CURRENT_USER|SESSION_USER}][USING(condition)][WITHCHECK(condition)];USING用于 SELECT、UPDATE、DELETE 的行过滤条件。

WITH CHECK用于 INSERT 和 UPDATE 的新行校验条件确保插入/更新后的行仍符合策略。

若省略FOR默认为ALL即同时作用于所有操作。

若省略TO默认为PUBLIC所有用户。

3 适用场景与局限

适用场景多租户 SaaS 应用数据隔离医疗/金融系统患者/客户数据隐私内部系统员工只能看本部门数据GDPR/CCPA 合规限制个人数据访问

局限与

注意事项不适用于临时表。

COPY 命令绕过 RLS因 COPY 是底层数据导入非 SQL 操作。

逻辑复制Logical Replication可能受影响订阅端需同步 RLS 策略。

外键约束不受 RLS 影响即使子表行因 RLS 不可见外键仍会校验。

视图上的 RLS若视图基于启用了 RLS 的表策略仍会生效。

4 实践建议始终通过会话变量传递上下文使用SET app.tenant_id xxx而非在每条 SQL 中传参避免应用层遗漏。

策略条件尽量简单避免在USING中调用高开销函数或子查询。

为 RLS 字段建立索引尤其是高频过滤的租户 ID、用户 ID 等。

测试覆盖所有角色和边界情况包括无权限用户、跨租户访问、插入非法数据等。

不要依赖 RLS 实现完整安全体系RLS 是访问控制的最后一道防线应用层仍需做基本校验。

文档化策略逻辑在代码注释或数据库文档中说明 RLS 规则便于维护。

实战案例场景1多租户 SaaS 应用假设有一张projects表每个项目属于一个租户tenant_id要求用户只能访问自己租户的数据。

建表并启用 RLSCREATETABLEprojects(idSERIALPRIMARYKEY,tenant_idTEXTNOTNULL,nameTEXTNOTNULL);ALTERTABLEprojectsENABLEROWLEVELSECURITY;

创建策略用户只能访问其租户的项目CREATEPOLICY tenant_isolation_policyONprojectsFORALLTOPUBLICUSING(tenant_idcurrent_setting(app.current_tenant));这里使用current_setting(app.current_tenant)获取会话级租户 ID需提前设置。

应用层设置租户上下文在每次数据库会话开始时由应用设置租户标识SETapp.current_tenantacme_corp;此后所有查询自动附加WHERE tenant_id acme_corp。

测试效果-- 用户只能看到自己租户的项目SELECT*FROMprojects;-- 自动过滤-- 插入时自动校验 tenant_idINSERTINTOprojects(tenant_id,name)VALUES(other_tenant,Bad Project);-- 报错new row violates row-level security policy for table projects场景2员工只能查看自己的薪资CREATETABLEsalaries(emp_idINT,amountNUMERIC,visible_toTEXT-- 可见范围self, manager, hr);ALTERTABLEsalariesENABLEROWLEVELSECURITY;-- 策略普通员工只能看自己的HR 可看全部CREATEPOLICY salary_view_policyONsalariesFORSELECTTOemployee_roleUSING(emp_idcurrent_user_id()ORvisible_tohr);-- 假设存在函数 current_user_id() 返回当前用户ID

高级用法

1 不同操作使用不同条件CREATEPOLICY project_policyONprojectsFORSELECTUSING(tenant_idcurrent_setting(app.current_tenant))FORINSERTWITHCHECK(tenant_idcurrent_setting(app.current_tenant));

2 多策略组合可为同一表创建多个策略PostgreSQL 会按以下规则合并同一角色、同一操作类型的多个策略 →OR关系不同角色的策略 → 各自独立生效示例允许用户访问自己或公开的项目CREATEPOLICY user_projectsONprojectsFORSELECTTOapp_userUSING(owner_idcurrent_user_id());CREATEPOLICY public_projectsONprojectsFORSELECTTOapp_userUSING(is_publictrue);最终条件owner_id ? OR is_public true

3 强制对表所有者生效ALTERTABLEprojectsFORCEROWLEVELSECURITY;此后即使表所有者执行查询也受 RLS 限制。

4 使用函数封装复杂逻辑CREATEFUNCTIONcan_access_project(proj_idINT)RETURNSBOOLEANAS$$BEGIN-- 复杂业务逻辑检查角色、时间、审批状态等RETURNEXISTS(SELECT1FROMaccess_rulesWHERE...);END;$$LANGUAGEplpgsql STABLE;CREATEPOLICY complex_policyONprojectsUSING(can_access_project(id));注意函数应标记为STABLE或IMMUTABLE避免在每行调用时产生副作用。

性能影响与优化

1 执行计划变化RLS 策略会被合并到查询的 WHERE 条件中可能影响索引选择。

示例-- 无 RLS 时SELECT*FROMprojectsWHEREnameAlpha;-- 可走 name 索引-- 有 RLS 时策略tenant_id ?-- 实际执行SELECT * FROM projects WHERE tenant_id ? AND name Alpha;-- 需要复合索引 (tenant_id, name)

2 索引建议为 RLS 过滤字段如tenant_id创建索引。

若常与其它条件组合查询创建复合索引CREATEINDEXidx_projects_tenant_nameONprojects(tenant_id,name);

3 避免复杂函数RLS 条件中的函数若计算开销大会导致全表扫描。

应尽量使用简单列比较。

管理与调试

1 查看现有策略-- 查看某表的所有策略SELECT*FROMpg_policiesWHEREtablenameprojects;-- 或使用 psql 命令\dprojects

2 临时禁用 RLS调试用-- 会话级禁用需 superuser 或 bypassrls 权限SETrow_securityTOOFF;-- 恢复SETrow_securityTOON;普通用户无法关闭 RLS除非被授予BYPASSRLS权限ALTERROLE auditorWITHBYPASSRLS;

3 日志监控开启日志可观察 RLS 是否生效# postgresql.conf log_statement all查询日志中会显示实际执行的带过滤条件的 SQL。

麻花传媒免费网站在线观看-麻花传媒免费网站在线观看应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123