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

基于Origin头的PostgreSQL RLS策略失效排查及方案咨询

问题描述

我需要校验请求的Origin头并与我的域名比对,确保只有本站点用户能修改数据库数据。了解到可以通过current_setting('request.headers.origin')实现该功能,于是使用了以下PL/pgSQL函数:

CREATE OR REPLACE FUNCTION rls_check(origin text)
RETURNS boolean AS $$
BEGIN
   RETURN origin = 'https://******.netlify.app';
END;
$$ LANGUAGE plpgsql;

其中星号部分是我的真实站点域名,已和请求头中的值确认一致。同时配置了RLS规则:

CREATE POLICY my_table_policy ON my_table
   FOR ALL
   TO my_user
   USING (rls_check(current_setting('request.headers.origin')) = true);

我对SQL了解不多,原本认为配置没问题,但添加后无论是手动编写请求还是通过SQL编辑器操作,都会返回404错误;只有把函数改成RETURN true时一切正常。想知道哪里操作有误,可能的问题是什么,还有哪些解决方案。

问题分析与解决方案

可能的问题点

  • request.headers.origin未传递或不存在:当请求没有携带Origin头,或者PostgreSQL未接收到该请求头时,current_setting('request.headers.origin')会直接抛出错误,最终导致请求返回404。而函数直接返回true时不会触发这个取值操作,因此不会报错。
  • Origin值匹配不严谨:实际请求的Origin可能存在大小写差异、末尾带斜杠(如https://******.netlify.app/)或多余空格,导致字符串精确匹配失败,RLS规则拒绝访问,返回404。
  • RLS策略权限范围不符:策略指定了TO my_user,如果请求使用的数据库账号不是my_user,或者表未启用行级安全(RLS),策略不会生效,同样会导致访问被拒绝。

解决方案

1. 处理Origin头不存在的情况

修改函数,先判断request.headers.origin是否存在,避免抛出错误:

CREATE OR REPLACE FUNCTION rls_check()
RETURNS boolean AS $$
DECLARE
  origin text;
BEGIN
  -- 第二个参数为true时,不存在该设置会返回null而非报错
  origin := current_setting('request.headers.origin', true);
  RETURN origin = 'https://******.netlify.app';
END;
$$ LANGUAGE plpgsql;

同时更新RLS策略,无需传递参数:

CREATE POLICY my_table_policy ON my_table
   FOR ALL
   TO my_user
   USING (rls_check() = true);

2. 宽松匹配Origin值

如果担心Origin格式有细微差异,可以做标准化处理后再匹配:

CREATE OR REPLACE FUNCTION rls_check()
RETURNS boolean AS $$
DECLARE
  origin text;
BEGIN
  origin := current_setting('request.headers.origin', true);
  -- 去掉末尾斜杠后再匹配
  RETURN trim(trailing '/' from origin) = 'https://******.netlify.app';
END;
$$ LANGUAGE plpgsql;

若需允许子域名访问,可使用模糊匹配:

RETURN origin LIKE 'https://%.netlify.app';

3. 验证RLS策略有效性

  • 确认当前操作的数据库用户为my_user:执行SELECT current_user;查看。
  • 确保表已启用RLS:执行ALTER TABLE my_table ENABLE ROW LEVEL SECURITY;(未启用的话策略不会生效)。
  • 手动测试函数返回值:执行SELECT rls_check('https://******.netlify.app');,确认是否返回true。

4. 备选方案:直接在RLS策略中校验

无需单独编写函数,直接在策略中完成校验并处理Origin不存在的情况:

CREATE POLICY my_table_policy ON my_table
   FOR ALL
   TO my_user
   USING (
     current_setting('request.headers.origin', true) = 'https://******.netlify.app'
   );

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 03:07:34