Liigu sisu juurde

Enable RLS in Supabase: mida tabel pärast tagastab

Vaata MarkdowninaAva rakenduses ClaudeAva rakenduses ChatGPTAva rakenduses Perplexity

Küsimus kopeeritakse ka. Kui vestlus avaneb tühjana, kleepige see sisse.

Lühidalt

RLS lülitatakse Supabase’is sisse ühe lausega tabeli kohta, alter table public.todos enable row level security;, või armatuurlaua valikuga “Enable RLS”. SQL-redaktoris või migratsiooniga loodud tabelid seda vaikimisi ei saa. Kohe pärast sisselülitamist jääb tabel vaikseks, mitte lärmakaks. Minu kohalikul testil said avalik võti ja kaks sisselogitud kasutajat select’ile, update’ile ja delete’ile 200 [] ning ainult insert ebaõnnestus veaga 42501. Salajane võti nägi ikka kõiki 3 rida. Tavaline vaade (view) tabeli peal andis avalikule võtmele ikka kõik 3 rida. 30. oktoobrist 2026 vajab uus tabel enne mis tahes ligipääsu ka granti, nii et lülitage RLS sisse ja kirjutage poliitikad samas migratsioonis kui grant.

Haldan tasuta Supabase’i turvakontrolli ja “RLS disabled” on leid, mida selgitatakse kõige halvemini. Enamik juhendeid ütleb, et pärast RLS-i sisselülitamist “tabel muutub kättesaamatuks”. See on lugemise kohta tõsi ja kirjutamise kohta eksitav. Seepärast tegin ühe tabeli kohalikule Supabase’i stackile ja saatsin sellele igat sorti päringuid: avaliku võtmega, kahe sisselogitud kasutajana ja salajase võtmega, pärast iga allolevat sammu.

Mis on RLS Supabase’is?

RLS (row-level security) on Postgresi funktsioon, mis filtreerib ridu päringu kaupa. Supabase muudab iga supabase-js päringu andmebaasipäringuks, mis käivitatakse rollina: anon avaliku (anon, publishable) võtme jaoks ja authenticated sisselogitud kasutaja jaoks. RLS-iga sees kontrollib Postgres teie poliitikaid iga rea kohta ning tagastab, muudab või kustutab ainult need read, mille mõni poliitika lubab. RLS-ita jõuab iga roll, millel on tabelil grant, igale reale.

Salajane (service role) võti on teistsugune. Selle rollil on BYPASSRLS, nii et RLS sellele kunagi ei kehti. Seepärast kuulub see ainult serverisse. Vahe kahe võtme vahel on artiklis Supabase anon key vs service role key: mida kumbki avab.

Kuidas enable RLS in Supabase tehakse?

Kolmel viisil, olenevalt sellest, kuidas tabel tehti:

  • Kui loote tabeli Table Editoris, jätke “Enable Row Level Security (RLS)” märgituks. Supabase’i armatuurlaua lähtekoodis on see märgitud “Recommended” ja selle väljalülitamine näitab hoiatust, et tabel on avalikult loetav ja kirjutatav.
  • Olemasoleva tabeli jaoks ütleb Supabase’i API turvajuhend: minge jaotisse Database, siis Policies ja valige tabelil “Enable RLS”.
  • SQL-iga SQL-redaktoris või migratsioonis:
alter table public.todos enable row level security;

Supabase’i juhend ütleb selgelt, et armatuurlaual loodud tabelitel on RLS vaikimisi sees ning SQL-redaktoris või muu tööriistaga loodud tabelitel mitte. Kui ehitate skeemi migratsioonide või tehisintellekti tööriistaga, kontrollige iga tabelit.

Mis juhtub kohe pärast RLS-i sisselülitamist?

Miski ei anna viga peale insert’i. Lõin tabeli public.todos omanikuveeruga (user_id uuid default auth.uid()), andsin sellele API rollidele grandid nii, nagu vanemates projektides, ja lisasin kolm rida: kaks kasutaja A ja ühe kasutaja B oma. Seejärel lülitasin RLS-i sisse ilma poliitikata:

Päring Avalik võti Kasutaja A Kasutaja B Salajane võti
Select 200, 0 rida 200, 0 rida 200, 0 rida 200, 3 rida
Insert oma rida 401, viga 42501 403, viga 42501 403, viga 42501 201, rida lisatud
Update rida 200, 0 rida 200, 0 rida 200, 0 rida 200, 1 rida
Delete rida 200, 0 rida 200, 0 rida 200, 0 rida 200, 1 rida

Insert’i viga kõlab new row violates row-level security policy. Update ja delete vastavad 200 ja tühja massiiviga, nii et rakendus, mis ei kontrolli tagastatud ridu, teatab “salvestatud”, kuigi midagi ei salvestatud. Lugege oma kirjutatu pärast RLS-i sisselülitamist tagasi või küsige loendust päisega Prefer: count=exact.

Enne RLS-i sai avalik võti samade grantidega lugeda kõiki 3 rida, lisada ridu ning muuta või kustutada mis tahes rida. Kasutaja A sai muuta ja kustutada kasutaja B rida ning anda oma read B-le.

Kuidas tabel uuesti kasutatavaks teha?

Kirjutage poliitika iga operatsiooni kohta. Tavaline oma ridade komplekt:

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

Nendega nägi kasutaja A oma 2 rida ja kasutaja B oma 1. Avalik võti nägi ikka 0. Kui A proovis lisada rea, mille omanik on B, või viia oma rea B-le, oli vastus 403, 42501. Selle keelduse annab update’i with check. Kui A proovis muuta või kustutada B rida, oli vastus 200, 0 rida. Rohkem mustreid (avalikud profiilid, tiimid, MFA) on artiklis Supabase RLS policy näited, testitud API kaudu.

Üks tähelepanek salajase võtme kohta: rida, mille see lisas, sai user_id = null, sest auth.uid()-l pole selle võtme taga kasutajat. RLS jäi vahele, kuid vaikeväärtus ei teinud seda, mida veeru nimi vihjab.

Mida avalik võti iga sammu järel luges?

Avaliku võtme loetud read, 3-st. Üks Supabase'i tabel 3 reaga, iga sammu järel. Uus tabel, grant puudub, RLS väljas (viga 42501): 0; Grant lisatud, RLS väljas: 3; RLS sees, poliitikat pole: 0; RLS sees, oma ridade poliitikad: 0; Tavaline vaade tabeli peal: 3; Vaade, security_invoker: 0.
Joonis 1. Kohalik Supabase'i stack (CLI 2.109.1, Postgres 17.6), 28. oktoober 2026.

Kaks sammu lekitavad kõik: grant ilma RLS-ita ja tavaline vaade tabeli peal, millel on korrektsed poliitikad. Järgmised kaks jaotist selgitavad mõlemat.

Kas RLS-i on pärast 30. oktoobri granti muudatust ikka vaja?

Jah. 30. oktoobrist 2026 ei anna Supabase enam skeemi public uutele tabelitele API rollidele automaatseid granteid, nii uutes kui olemasolevates projektides. Minu kohalik stack käitub juba nii. Värskelt loodud tabel RLS-ita vastas igale rollile 42501, salajane võti kaasa arvatud, nii et miski ei lekkinud. Üksikasjad on artiklis Supabase 30. oktoobri grantide muudatus: mis läheb katki.

Kuid grant tuleb tagasi niipea, kui rakendus tabelit vajab, ja sellest hetkest on RLS ainus asi avaliku võtme ja iga rea vahel. Seega pange kõik ühte migratsiooni, selles järjekorras:

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;

Andke grant ainult rollidele, kes tabelit vajavad. Kui võtsin rollilt anon kõik tagasi, muutus avaliku võtme select’i vastus 200 []-st 401, 42501-ks. Grant on esimene lukk, RLS teine.

Miks vaade ikka ridu lekitab?

Sest vaade töötab oma omaniku õigustega ja Supabase’is on see postgres, mis jätab RLS-i vahele. Kui todos-il olid oma ridade poliitikad, tagastas tavaline create view public.todos_view as select * from public.todos kõik 3 rida avalikule võtmele ja kasutajale B.

Kui sama vaade loodi uuesti with (security_invoker = true), tagastas see avalikule võtmele 0 rida, A-le 2 ja B-le 1, täpselt nagu tabel:

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

Supabase’i Advisor märgib tavalise vaate koodiga security_definer_view; mida see tähendab ja kuidas seda parandada, on märkmes Supabase security definer view: miks see jätab RLS vahele.

Kuidas RLS iga uue tabeli jaoks automaatselt sisse lülitada?

Sündmusetriggeriga. Supabase’i event triggers juhend annab funktsiooni rls_auto_enable() ja triggeri ensure_rls, mis käivitub pärast lauseid create table, create table as ja select into skeemis public. Paigaldasin selle nii, nagu avaldatud, ja sain:

  • Hiljem lausega create table loodud tabelil oli RLS sees ilma alter-ita. Avalik võti sai select’ile 200 [] ja insert’ile 401.
  • Lausega create table as select loodud tabelil oli RLS samuti sees.
  • Enne triggerit loodud tabel jäi välja. Trigger ei tööta tagasiulatuvalt.

Ilma triggerita oli kaitstud tabeli kõrvale loodud teisel tabelil RLS väljas ja kui sellele anti grant, luges ja kirjutas avalik võti seda vabalt. Trigger katab ka ainult skeemi public; teised avaldatud skeemid vajavad funktsioonis oma rida.

Kas FORCE ROW LEVEL SECURITY aitab?

Mitte rollidele, mille pärast tasub muretseda. alter table ... force row level security paneb RLS-i kehtima ka tabeli omanikule. Supabase’is on nii postgres kui ka service_role rollidel BYPASSRLS, nii et pärast force-i luges omanik ikka 3 rida, salajane võti nägi ikka kõike ja postgres-i omandis vaade lekkis ikka. See muutis midagi ainult minu loodud omanikurolli puhul ilma BYPASSRLS-ita: 2 rida enne, 0 pärast.

Kuidas oma projekti kontrollida?

  • Loetlege SQL-redaktoris skeemi public tabelid, millel RLS on väljas:
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;

Kuidas testisin

  • Supabase CLI 2.109.1 sülearvutis: Postgres 17.6, PostgREST 14.14, Auth 2.192.0. Kaks kasutajat logisid sisse parooliga, lisaks kohalikud publishable- ja secret-võtmed.
  • Üks tabel, public.todos, enne iga päringut samade 3 reaga uuesti täidetud. Iga samm rakendati SQL-ina ja iga päring läks läbi REST API, oleku kood ja sisu salvestatud.
  • Sammude 2 kuni 5 grandid lisati käsitsi, et vastata enne 30. oktoobrit 2026 loodud projektile.

Piirangud. Üks kohalik stack, väljamõeldud andmed, 28. oktoober 2026. Armatuurlaua sammud on Supabase’i dokumentatsioonist tsiteeritud, mitte läbi klõpsatud. Armatuurlaua enda rolliga loodud tabelitel võivad olla teised vaikegrandid. Seda ma ei testinud, samuti mitte Storage’i, Realtime’i ega GraphQL-i.

Pole kindel, et teie tabelid on lukus?

Vaatan hea meelega koos teiega skeemi üle. Ilma müügijututa.

Võtke ühendust

© 2026 Denys Zaichenko. Algne artikkel: https://madsalt.tech/et/blog/how-to-enable-rls-in-supabase/