我有一个
trips
表和 users
表,以及一个 trip_user
连接表来处理 trips
和 users
表的多对多关系。
我想实施一项 RLS 策略,仅允许经过身份验证的用户查看
users
的数据,这些数据是同一行程的一部分。
我一直在尝试在我的 Supabase 应用程序中实现此功能,但我一直遇到错误:
在关系“trip_user”的策略中检测到无限递归
这是我当前实现的片段。
alter policy "Enable users to view their trips"
on "public"."trips"
to authenticated
using (
(id IN ( SELECT trip_user.trip_id
FROM trip_user))
);
alter policy "Enable users to view their users that are part of the same trip"
on "public"."trips"
to authenticated
using (
(trip_id IN ( SELECT trip.id
FROM trip))
);
您收到
infinite recursion detected in policy
错误,因为 trips
表和 users
表上的当前 RLS 策略直接引用它们所应用的相同表,从而导致无限循环。
要在 PostgreSQL(或 Supabase)中实现多对多关系的行级安全性 (RLS),您需要依靠
trip_user
连接表进行过滤逻辑来避免递归:
我们假设:
users
表:用户详细信息(id 为主键)。
trips
表:行程详情(id 为主键)。
trip_user
表:链接行程和用户的连接表(trip_id
、user_id
作为外键)。
trips
的 RLS 政策:
ALTER POLICY "Enable users to view their trips"
ON public.trips
TO authenticated
USING (
EXISTS (
SELECT 1
FROM public.trip_user
WHERE trip_user.trip_id = trips.id
AND trip_user.user_id = auth.uid()
)
);
RLS 政策
users
ALTER POLICY "Enable users to view users in the same trips"
ON public.users
TO authenticated
USING (
EXISTS (
SELECT 1
FROM public.trip_user AS tu1
JOIN public.trip_user AS tu2
ON tu1.trip_id = tu2.trip_id
WHERE tu1.user_id = auth.uid()
AND tu2.user_id = users.id
)
);
trip_user
的 RLS 策略(可选 - 如果用户需要查询
trip_user
表,请使用此策略):
ALTER POLICY "Enable users to view trip-user relationships for their trips"
ON public.trip_user
TO authenticated
USING (
EXISTS (
SELECT 1
FROM public.trip_user
WHERE trip_user.trip_id = trip_user.trip_id
AND trip_user.user_id = auth.uid()
)
);
说明
trip_user
表 过滤,避免对
trips
或
users
表进行递归查询。
auth.uid()
功能(可在 Supabase)获取当前用户的 ID,确保策略有效 动态应用于经过身份验证的用户。
users
政策使用自加入
trip_user
表,用于识别与该用户共享相同行程的用户 经过身份验证的用户。
ALTER TABLE public.trips ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.trip_user ENABLE ROW LEVEL SECURITY;