Pāriet uz saturu

Enable RLS in Supabase: ko tabula atgriež pēc tam

Skatīt kā MarkdownAtvērt pakalpojumā ClaudeAtvērt pakalpojumā ChatGPTAtvērt pakalpojumā Perplexity

Jautājums tiek arī nokopēts. Ja tērzēšana atveras tukša, ielīmējiet to.

Īsumā

RLS Supabase ieslēdz ar vienu teikumu katrai tabulai, alter table public.todos enable row level security;, vai ar opciju “Enable RLS” vadības panelī. Tabulas, kas izveidotas SQL redaktorā vai ar migrāciju, to pēc noklusējuma nesaņem. Tūlīt pēc ieslēgšanas tabula kļūst klusa, nevis skaļa. Manā lokālajā testā publiskā atslēga un divi pierakstīti lietotāji saņēma 200 [] uz select, update un delete, un tikai insert beidzās ar kļūdu 42501. Slepenā atslēga joprojām redzēja visas 3 rindas. Parasts skats (view) virs tabulas publiskajai atslēgai joprojām atdeva visas 3 rindas. Kopš 2026. gada 30. oktobra jaunai tabulai pirms jebkādas piekļuves vajag arī grantu, tāpēc ieslēdziet RLS un rakstiet politikas tajā pašā migrācijā, kur grants.

Es uzturu bezmaksas Supabase drošības pārbaudi, un “RLS disabled” ir atradums, ko skaidro vissliktāk. Lielākā daļa pamācību saka, ka pēc RLS ieslēgšanas “tabula kļūst nepieejama”. Lasīšanai tā ir taisnība, rakstīšanai maldinoši. Tāpēc izveidoju vienu tabulu lokālā Supabase stekā un sūtīju tai visu veidu pieprasījumus: ar publisko atslēgu, kā diviem pierakstītiem lietotājiem un ar slepeno atslēgu, pēc katra tālāk minētā soļa.

Kas ir RLS Supabase?

RLS (row-level security) ir Postgres funkcija, kas filtrē rindas katram pieprasījumam. Supabase katru supabase-js pieprasījumu pārvērš datubāzes vaicājumā, kas darbojas kā loma: anon publiskajai (anon, publishable) atslēgai un authenticated pierakstītam lietotājam. Ar ieslēgtu RLS Postgres pārbauda jūsu politikas katrai rindai un atgriež, maina vai dzēš tikai tās rindas, ko kāda politika atļauj. Bez RLS jebkura loma, kurai tabulai ir grants, piekļūst katrai rindai.

Slepenā (service role) atslēga ir citāda. Tās lomai ir BYPASSRLS, tāpēc RLS uz to nekad neattiecas. Tāpēc tā pieder tikai serverim. Atšķirība starp abām atslēgām ir rakstā Supabase anon key vs service role key: ko katra atver.

Kā enable RLS in Supabase?

Trīs veidos, atkarībā no tā, kā tabula tika izveidota:

  • Veidojot tabulu Table Editor, atstājiet atzīmētu “Enable Row Level Security (RLS)”. Supabase vadības paneļa pirmkodā tas ir atzīmēts kā “Recommended”, un tā izslēgšana parāda brīdinājumu, ka tabula būs publiski lasāma un rakstāma.
  • Esošai tabulai Supabase API drošības ceļvedis saka: dodieties uz Database, tad Policies un tabulai izvēlieties “Enable RLS”.
  • Ar SQL SQL redaktorā vai migrācijā:
alter table public.todos enable row level security;

Supabase ceļvedis skaidri norāda, ka vadības panelī izveidotām tabulām RLS pēc noklusējuma ir ieslēgts, bet SQL redaktorā vai ar citu rīku izveidotām nav. Ja shēmu veidojat ar migrācijām vai mākslīgā intelekta rīku, pārbaudiet katru tabulu.

Kas notiek tūlīt pēc RLS ieslēgšanas?

Nekas nedod kļūdu, izņemot insert. Izveidoju tabulu public.todos ar īpašnieka kolonnu (user_id uuid default auth.uid()), piešķīru tai grantus API lomām tā, kā vecākos projektos, un pievienoju trīs rindas: divas lietotājam A un vienu lietotājam B. Pēc tam ieslēdzu RLS bez politikas:

Pieprasījums Publiskā atslēga Lietotājs A Lietotājs B Slepenā atslēga
Select 200, 0 rindas 200, 0 rindas 200, 0 rindas 200, 3 rindas
Insert savu rindu 401, kļūda 42501 403, kļūda 42501 403, kļūda 42501 201, rinda pievienota
Update rindai 200, 0 rindas 200, 0 rindas 200, 0 rindas 200, 1 rinda
Delete rindai 200, 0 rindas 200, 0 rindas 200, 0 rindas 200, 1 rinda

Insert kļūda skan new row violates row-level security policy. Update un delete atbild ar 200 un tukšu masīvu, tāpēc lietotne, kas nepārbauda atgrieztās rindas, ziņo “saglabāts”, kaut gan nekas netika saglabāts. Pēc RLS ieslēgšanas nolasiet savus ierakstus atpakaļ vai pieprasiet skaitu ar Prefer: count=exact.

Pirms RLS ar tiem pašiem grantiem publiskā atslēga varēja nolasīt visas 3 rindas, pievienot rindas un mainīt vai dzēst jebkuru rindu. Lietotājs A varēja rediģēt un dzēst lietotāja B rindu un atdot savas rindas B.

Kā tabulu atkal padarīt lietojamu?

Uzrakstiet politiku katrai operācijai. Parastais savu rindu komplekts:

create policy "own select" on public.todos for select to authenticated
  using ((select auth.uid()) = user_id);
create policy "own insert" on public.todos for insert to authenticated
  with check ((select auth.uid()) = user_id);
create policy "own update" on public.todos for update to authenticated
  using ((select auth.uid()) = user_id) with check ((select auth.uid()) = user_id);
create policy "own delete" on public.todos for delete to authenticated
  using ((select auth.uid()) = user_id);

Ar šīm politikām lietotājs A redzēja savas 2 rindas un lietotājs B savu 1. Publiskā atslēga joprojām redzēja 0. Kad A mēģināja pievienot rindu, kuras īpašnieks ir B, vai nodot savu rindu B, atbilde bija 403, 42501. Šo atteikumu dod update with check. Kad A mēģināja mainīt vai dzēst B rindu, atbilde bija 200, 0 rindas. Vairāk paraugu (publiski profili, komandas, MFA) ir rakstā Supabase RLS policy piemēri, pārbaudīti caur API.

Viena detaļa par slepeno atslēgu: rinda, ko tā pievienoja, ieguva user_id = null, jo aiz šīs atslēgas auth.uid() nav lietotāja. RLS tika izlaists, bet noklusējums nedarīja to, ko liek domāt kolonnas nosaukums.

Ko publiskā atslēga nolasīja pēc katra soļa?

Rindas, ko publiskā atslēga nolasīja, no 3. Viena Supabase tabula ar 3 rindām, pēc katra soļa. Jauna tabula, bez granta, RLS izslēgts (kļūda 42501): 0; Grants pievienots, RLS izslēgts: 3; RLS ieslēgts, bez politikas: 0; RLS ieslēgts, savu rindu politikas: 0; Parasts skats virs tabulas: 3; Skats, security_invoker: 0.
1. attēls. Lokālais Supabase steks (CLI 2.109.1, Postgres 17.6), 2026. gada 28. oktobris.

Divi soļi izlaiž visu: grants bez RLS un parasts skats virs tabulas ar pareizām politikām. Nākamās divas sadaļas izskaidro abus.

Vai RLS joprojām vajadzīgs pēc 30. oktobra grantu izmaiņām?

Jā. Kopš 2026. gada 30. oktobra Supabase jaunām tabulām shēmā public vairs nedod automātiskus grantus API lomām, jaunos un esošos projektos. Mans lokālais steks jau tā uzvedas. Tikko izveidota tabula bez RLS atbildēja 42501 katrai lomai, slepeno atslēgu ieskaitot, tāpēc nekas neizplūda. Detaļas ir rakstā Supabase 30. oktobra izmaiņas: kas salūzīs, kā pārbaudīt.

Bet grants atgriežas, tiklīdz lietotnei tabula ir vajadzīga, un no tā brīža RLS ir vienīgais, kas stāv starp publisko atslēgu un katru rindu. Tāpēc visu liekiet vienā migrācijā šādā secībā:

create table public.todos (...);
alter table public.todos enable row level security;
create policy "own select" on public.todos ...;
grant select, insert, update, delete on table public.todos to authenticated;

Piešķiriet grantu tikai lomām, kurām tabula vajadzīga. Kad atņēmu lomai anon visu, publiskās atslēgas select atbilde mainījās no 200 [] uz 401, 42501. Grants ir pirmā slēdzene, RLS otrā.

Kāpēc skats joprojām izplūdina rindas?

Tāpēc, ka skats darbojas ar sava īpašnieka tiesībām, un Supabase tas ir postgres, kas apiet RLS. Kad todos bija savu rindu politikas, parasts create view public.todos_view as select * from public.todos atdeva visas 3 rindas publiskajai atslēgai un lietotājam B.

Kad to pašu skatu izveidoja no jauna ar with (security_invoker = true), tas publiskajai atslēgai atdeva 0 rindu, A 2 un B 1, tieši kā tabula:

create view public.todos_view with (security_invoker = true) as
  select * from public.todos;

Supabase Advisor parastu skatu atzīmē ar security_definer_view; ko tas nozīmē un kā to labot, ir piezīmē Supabase security definer view: kāpēc tas apiet RLS.

Kā automātiski ieslēgt RLS katrai jaunai tabulai?

Ar notikuma trigeri. Supabase event triggers ceļvedis dod funkciju rls_auto_enable() un trigeri ensure_rls, kas darbojas pēc create table, create table as un select into shēmā public. Uzstādīju to tā, kā publicēts, un ieguvu:

  • Vēlāk ar create table izveidotai tabulai RLS bija ieslēgts bez alter. Publiskā atslēga saņēma 200 [] uz select un 401 uz insert.
  • Ar create table as select izveidotai tabulai RLS arī bija ieslēgts.
  • Pirms trigera izveidota tabula palika izslēgta. Trigeris nedarbojas atpakaļejoši.

Bez trigera otrai tabulai, kas izveidota blakus aizsargātajai, RLS bija izslēgts, un pēc granta piešķiršanas publiskā atslēga to brīvi lasīja un rakstīja. Trigeris aptver arī tikai shēmu public; citām publicētām shēmām funkcijā vajadzīga sava rinda.

Vai FORCE ROW LEVEL SECURITY palīdz?

Ne tām lomām, par kurām vērts uztraukties. alter table ... force row level security liek RLS attiekties arī uz tabulas īpašnieku. Supabase gan postgres, gan service_role ir BYPASSRLS, tāpēc pēc force īpašnieks joprojām saskaitīja 3 rindas, slepenā atslēga joprojām redzēja visu, un postgres piederošs skats joprojām izplūdināja. Tas kaut ko mainīja tikai manis izveidotai īpašnieka lomai bez BYPASSRLS: 2 rindas pirms, 0 pēc.

Kā pārbaudīt savu projektu?

  • SQL redaktorā uzskaitiet shēmas public tabulas ar izslēgtu RLS:
select c.relname as table_name
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public'
  and c.relkind in ('r', 'p')
  and not c.relrowsecurity
order by 1;

Kā testēju

  • Supabase CLI 2.109.1 portatīvajā datorā: Postgres 17.6, PostgREST 14.14, Auth 2.192.0. Divi lietotāji pierakstījās ar paroli, plus lokālās publishable un secret atslēgas.
  • Viena tabula, public.todos, pirms katra pieprasījuma no jauna aizpildīta ar tām pašām 3 rindām. Katrs solis tika pielietots kā SQL, un katrs pieprasījums gāja caur REST API, statusa kods un saturs ierakstīti.
  • Grantus 2. līdz 5. solim pievienoju ar roku, lai atbilstu projektam, kas izveidots pirms 2026. gada 30. oktobra.

Ierobežojumi. Viens lokāls steks, izdomāti dati, 2026. gada 28. oktobris. Vadības paneļa soļi citēti no Supabase dokumentācijas, nevis izklikšķināti. Tabulām, ko izveido paša vadības paneļa loma, var būt citi noklusējuma granti. To es netestēju, tāpat kā Storage, Realtime vai GraphQL.

Neesat drošs, ka jūsu tabulas ir aizslēgtas?

Labprāt kopā ar jums apskatīšu shēmu. Bez pārdošanas.

Sazināties

© 2026 Denys Zaichenko. Oriģinālais raksts: https://madsalt.tech/lv/blog/how-to-enable-rls-in-supabase/