Pereiti prie turinio

How to enable RLS in Supabase: ką grąžina API

Žiūrėti kaip MarkdownAtidaryti per ClaudeAtidaryti per ChatGPTAtidaryti per Perplexity

Klausimas taip pat nukopijuojamas. Jei pokalbis atsidaro tuščias, įklijuokite jį.

Trumpai

RLS Supabase įjungiate vienu sakiniu kiekvienai lentelei, alter table public.todos enable row level security;, arba dashboard pasirinkimu „Enable RLS“. Lentelės, sukurtos SQL redaktoriuje ar migracija, jo pagal nutylėjimą neturi. Iškart po įjungimo lentelė greičiau nutyla, nei pradeda šaukti. Mano vietiniame teste viešasis raktas ir du prisijungę vartotojai select, update ir delete gavo 200 [], o nepavyko tik insert, su 42501. Slaptasis raktas vis dar matė visas 3 eilutes. Paprastas vaizdas (view) virš lentelės viešajam raktui vis dar atiduodavo visas 3 eilutes. Nuo 2026 m. spalio 30 d. nauja lentelė taip pat reikalauja teisės (grant), kad kas nors ją pasiektų, todėl įjunkite RLS ir parašykite politikas toje pačioje migracijoje kaip ir grant.

Palaikau nemokamą Supabase saugumo patikrinimą, o „RLS disabled“ yra radinys, kuris paaiškinamas prasčiausiai. Dauguma vadovų sako, kad įjungus RLS lentelė „tampa nepasiekiama“. Skaitymui tai tiesa, rašymui klaidina. Todėl sukūriau vieną lentelę vietiniame Supabase stack ir po kiekvieno žemiau pateikto žingsnio siunčiau jai visų rūšių užklausas: kaip viešasis raktas, kaip du prisijungę vartotojai ir kaip slaptasis raktas.

Kas yra RLS Supabase?

RLS (row-level security) yra Postgres funkcija, filtruojanti eilutes kiekvienai užklausai. Supabase kiekvieną supabase-js užklausą paverčia duomenų bazės užklausa, vykdoma kaip rolė: anon viešajam raktui (anon, publishable), authenticated prisijungusiam vartotojui. Kai RLS įjungtas, Postgres kiekvienai eilutei tikrina jūsų politikas ir grąžina, keičia ar trina tik tas eilutes, kurias politika leidžia. Kai RLS išjungtas, bet kuri rolė, turinti teisę į lentelę, pasiekia kiekvieną eilutę.

Slaptasis raktas (service role) kitoks. Jo rolė turi BYPASSRLS, todėl RLS jam niekada netaikomas. Todėl jis priklauso tik serveriui. Skirtumas tarp abiejų raktų aprašytas straipsnyje Supabase anon key vs service role key: ką jie atveria.

Kaip įjungti RLS Supabase?

Trimis būdais, priklausomai nuo to, kaip lentelė sukurta:

  • Kuriant lentelę Table Editor palikite pažymėtą „Enable Row Level Security (RLS)“. Supabase dashboard šaltinio kode tai pažymėta „Recommended“, o išjungus rodomas įspėjimas, kad lentelė bus viešai skaitoma ir rašoma.
  • Esamai lentelei Supabase API saugumo vadovas sako: eikite į Database, tada Policies ir prie lentelės pasirinkite „Enable RLS“.
  • SQL, SQL redaktoriuje arba migracijoje:
alter table public.todos enable row level security;

Supabase vadove aiškiai sakoma, kad dashboard sukurtos lentelės turi RLS įjungtą pagal nutylėjimą, o SQL redaktoriuje ar kitu įrankiu sukurtos – ne. Jei schemą kuriate migracijomis ar AI įrankiu, patikrinkite kiekvieną lentelę.

Kas nutinka iškart po RLS įjungimo?

Nieko neduoda klaidos, išskyrus insert. Sukūriau public.todos su savininko stulpeliu (user_id uuid default auth.uid()), suteikiau jai teises API rolėms taip, kaip senesni projektai, ir pridėjau tris eilutes: dvi, priklausančias vartotojui A, ir vieną vartotojui B. Tada įjungiau RLS be jokios politikos:

Užklausa Viešasis raktas Vartotojas A Vartotojas B Slaptasis raktas
Select 200, 0 eilučių 200, 0 eilučių 200, 0 eilučių 200, 3 eilutės
Insert savo eilutės 401, klaida 42501 403, klaida 42501 403, klaida 42501 201, eilutė įterpta
Update eilutės 200, 0 eilučių 200, 0 eilučių 200, 0 eilučių 200, 1 eilutė
Delete eilutės 200, 0 eilučių 200, 0 eilučių 200, 0 eilučių 200, 1 eilutė

Insert klaida skamba new row violates row-level security policy. Update ir delete atsako 200 su tuščiu masyvu, todėl programa, netikrinanti grąžintų eilučių, praneša „išsaugota“, nors niekas neišsaugota. Įjungę RLS perskaitykite savo įrašus atgal arba paprašykite skaičiaus per Prefer: count=exact.

Prieš RLS, su tomis pačiomis teisėmis, viešasis raktas galėjo perskaityti visas 3 eilutes, įterpti ir keisti ar trinti bet kurią eilutę. Vartotojas A galėjo redaguoti ir ištrinti vartotojo B eilutę ir perduoti savo eilutes B.

Kaip vėl padaryti lentelę naudojamą?

Parašykite politiką kiekvienai operacijai. Įprastas savų eilučių rinkinys:

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);

Su jomis vartotojas A matė savo 2 eilutes, o vartotojas B savo 1. Viešasis raktas vis dar matė 0. Kai A bandė įterpti eilutę, priklausančią B, arba perkelti savo eilutę B, atsakymas buvo 403, 42501. Šis atmetimas ateina iš with check ties update. Kai A bandė pakeisti ar ištrinti vartotojo B eilutę, atsakymas buvo 200, 0 rows. Daugiau modelių (vieši profiliai, komandos, MFA) rasite straipsnyje Supabase RLS policy: pavyzdžiai, išbandyti per API.

Viena detalė su slaptuoju raktu: jo įterpta eilutė gavo user_id = null, nes už šio rakto auth.uid() neturi vartotojo. RLS buvo praleistas, bet numatytoji reikšmė nepadarė to, ką sufleruoja stulpelio pavadinimas.

Ką viešasis raktas skaitė kiekviename žingsnyje?

Eilutės, kurias skaitė viešasis raktas, iš 3. Viena Supabase lentelė su 3 eilutėmis, po kiekvieno žingsnio. Nauja lentelė, be grant, RLS off (klaida 42501): 0; Pridėtas grant, RLS off: 3; RLS on, be politikos: 0; RLS on, savų eilučių politikos: 0; Paprastas view virš lentelės: 3; View su security_invoker: 0.
1 pav. Vietinis Supabase stack (CLI 2.109.1, Postgres 17.6), 2026 m. spalio 28 d.

Du žingsniai nutekina viską: teisė (grant) be RLS ir paprastas view virš lentelės su teisingomis politikomis. Kiti du skyriai paaiškina abu.

Ar RLS vis dar reikalingas po spalio 30 d. grant pokyčio?

Taip. Nuo 2026 m. spalio 30 d. Supabase naujoms lentelėms public schemoje nebesuteikia automatinių teisių API rolėms, tiek naujuose, tiek esamuose projektuose. Mano vietinis stack jau taip elgiasi. Ką tik sukurta lentelė su išjungtu RLS visoms rolėms, įskaitant slaptąjį raktą, atsakė 42501, taigi niekas nenutekėjo. Detalės straipsnyje Supabase spalio 30 d. pokytis: kas sulūš ir kaip patikrinti.

Tačiau teisė sugrįžta, kai tik programai reikia lentelės, ir nuo tada RLS yra vienintelis dalykas tarp viešojo rakto ir visų eilučių. Todėl viską sudėkite į vieną migraciją, šia tvarka:

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;

Suteikite teisę tik rolėms, kurioms lentelės reikia. Kai iš anon atėmiau viską, viešojo rakto select pasikeitė iš 200 [] į 401, 42501. Teisė yra pirmas užraktas, RLS – antras.

Kodėl view vis dar nuteka eilutės?

Nes view veikia su savo savininko teisėmis, o Supabase tai yra postgres, kuris apeina RLS. Esant savų eilučių politikoms todos lentelėje, paprastas create view public.todos_view as select * from public.todos grąžino visas 3 eilutes viešajam raktui ir vartotojui B.

Perkūrus with (security_invoker = true), tas pats view viešajam raktui grąžino 0 eilučių, A – 2, B – 1, lygiai kaip lentelė:

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

Supabase Advisor paprastą rūšį pažymi kaip security_definer_view; ką tai reiškia ir kaip taisyti, rasite Supabase security definer view pastaboje.

Kaip automatiškai įjungti RLS kiekvienoje naujoje lentelėje?

Įvykio trigeriu (event trigger). Supabase event triggers vadove pateikta funkcija rls_auto_enable() ir trigeris ensure_rls, veikiantis po create table, create table as ir select into public schemoje. Įdiegiau jį tokį, koks paskelbtas, ir gavau:

  • Vėliau su create table sukurta lentelė turėjo RLS įjungtą be jokio alter. Viešasis raktas gavo 200 [] per select ir 401 per insert.
  • Su create table as select sukurta lentelė taip pat turėjo RLS įjungtą.
  • Prieš trigerį sukurta lentelė liko išjungta. Trigeris neveikia atgaline data.

Be trigerio antra lentelė, sukurta šalia apsaugotos, turėjo RLS išjungtą, o gavus teisę viešasis raktas ją laisvai skaitė ir rašė. Jis taip pat apima tik public; kitoms atvertoms schemoms funkcijoje reikia atskiros eilutės.

Ar padeda FORCE ROW LEVEL SECURITY?

Ne toms rolėms, dėl kurių nerimaujate. alter table ... force row level security priverčia RLS galioti ir lentelės savininkui. Supabase tiek postgres, tiek service_role turi BYPASSRLS, todėl po force savininkas vis tiek suskaičiavo 3 eilutes, slaptasis raktas vis tiek matė viską, o postgres valdomas view vis tiek nutekino. Tai pakeitė tik savininko rolę, kurią sukūriau be BYPASSRLS: 2 eilutės prieš, 0 po.

Kaip patikrinti savo projektą?

  • SQL redaktoriuje išvardykite public lenteles su išjungtu 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;
  • Advisor dashboard pateikia tą patį kaip rls_disabled_in_public; ką ši klaida reiškia, rasite RLS disabled in public pastaboje.
  • Nemokamas Supabase saugumo patikrinimas skaito jūsų projektą tik skaitymo režimu ir išvardija lenteles su išjungtu RLS, kurias API gali pasiekti, vaizdus (views), apeinančius RLS, ir politikas, leidžiančias visiems, kiekvienam su taisymo SQL.
  • Skeneris negali žinoti, kurios eilutės kam priklauso. Tam įrodyti siųskite užklausas kaip du vartotojai, kaip aukščiau. Pilnas metodas programai su rolėmis aprašytas straipsnyje Kaip testuoti Supabase RLS: 30 iš 87 leidimų nieko nedarė.

Kaip testavau

  • Supabase CLI 2.109.1 nešiojamajame kompiuteryje: Postgres 17.6, PostgREST 14.14, Auth 2.192.0. Du vartotojai, prisijungę slaptažodžiu, ir vietiniai publishable bei secret raktai.
  • Viena lentelė, public.todos, prieš kiekvieną užklausą iš naujo užpildyta tomis pačiomis 3 eilutėmis. Kiekvienas žingsnis pritaikytas kaip SQL, kiekviena užklausa ėjo per REST API, užfiksuojant jos būsenos kodą ir turinį.
  • Teisės 2–5 žingsniams pridėtos rankiniu būdu, kad atitiktų projektą, sukurtą prieš 2026 m. spalio 30 d.

Apribojimai. Vienas vietinis stack, išgalvoti duomenys, 2026 m. spalio 28 d. Dashboard žingsniai cituojami iš Supabase dokumentacijos, nepraklikinti. Lentelės, sukurtos paties dashboard rolės, gali turėti kitas numatytąsias teises. To netestavau, kaip ir Storage, Realtime ar GraphQL.

Nesate tikri, kad jūsų lentelės užrakintos?

Mielai kartu peržiūrėsiu schemą. Be pardavimo.

Susisiekti

© 2026 Denys Zaichenko. Originalus straipsnis: https://madsalt.tech/lt/blog/how-to-enable-rls-in-supabase/