atom.web-builder.rls-protect-data
RLSで「自分のデータだけ見える」を実現する
RLSで「自分のデータだけ見える」を実現する あなたが作っているサービスに、ユーザーそれぞれのメモや予約情報が保存されるとします。このとき「Aさんのデータが、ログインした別のBさんに見えてしまう」と大事故です。これ...
成果物成果物このレッスンが終わったとき、あなたの手元に残る具体的な成果物です(例: 公開済みの Web ページ、動作するフォームなど)。
証跡証跡成果物が正しく作れたことを確認するためのチェックリストです(例: ブラウザで動作する、フォーム送信で値が保存される)。
メディアメディアレッスン内に出てくる図や動画のスロットです。実際の画面やイメージで理解を補助します。
レッスン本文
RLSで「自分のデータだけ見える」を実現する
あなたが作っているサービスに、ユーザーそれぞれのメモや予約情報が保存されるとします。このとき「Aさんのデータが、ログインした別のBさんに見えてしまう」と大事故です。これを防ぐしくみが RLS(ロー・レベル・セキュリティ/=行単位のアクセス制御) です。
たとえるなら、アパートの郵便受けです。建物の中には全員分の郵便受けが並んでいますが、自分の鍵でしか自分のポストを開けられません。RLS はまさにこの「自分の鍵で自分の行だけ開ける」を、データベース側で強制するしくみです。
この Atom では、Supabase の notes テーブルに対して、最小の policy(=アクセス許可のルール)を1本書き切ります。所要時間の目安は15分です。

はじめに確認する前提
次の2つが終わっていることを前提にします。まだなら、先に該当 Atom に戻ってください。
- Supabase 側にテーブルが1つ作ってある(例:
notesテーブルにid,user_id,body列がある) - メールとパスワードでログインできるしくみが動いている
ポイントは、テーブルに user_id という列があり、そこに「このデータは誰のものか」が入っていることです。ここが RLS の「鍵と郵便受けの対応表」になります。
手順1: RLS を有効にする
Supabase のダッシュボード(=管理画面)を開き、左メニューの「Table Editor」から対象テーブル(例: notes)を選びます。右上の設定アイコンから 「Enable Row Level Security」(=行単位のアクセス制御をオンにする)をクリックします。

ここで重要な注意があります。RLS を有効にしただけで policy(許可ルール)を1本も書かないと、全員が何も見えない状態になります。つまり、この時点ではあなたのアプリから notes を取得しても空っぽになります。次の手順で最低1本の policy を必ず追加します。
手順2: 「自分の行だけ読める」policy を書く
ダッシュボードの「Authentication」→「Policies」から、対象テーブルに対して新しい policy を追加します。
AIにそのまま貼れるプロンプト例を示します。迷ったらまずこれを使ってください。
良い例のプロンプト:
Supabase の
notesテーブルに、ログイン中のユーザーが自分の行だけ SELECT できる RLS policy を1本書いてください。user_id列に所有者の UUID が入っています。policy 名、対象操作、条件式だけをコードブロックで出してください。余計な解説は不要です。
悪い例のプロンプト:
RLS 書いて
前者は「テーブル名・列名・操作・条件」がはっきりしているので、AI は迷いません。後者は情報が足りず、汎用的すぎる答えが返ってきます。
AI が返してくる SQL は、おおむね次のような1行条件を含むはずです(コピペ用)。
create policy "read own notes" on notes for select using (auth.uid() = user_id);
日本語に直すと、「notes テーブルの SELECT(=読み取り)について、今ログイン中の人の ID が、その行の user_id と一致するときだけ許可する」というルールです。
手順3: 書き込み・更新・削除も同じ発想で追加する
読み取りだけ許可しても、他人の行を更新・削除できてしまっては意味がありません。最低限、insert / update / delete にも policy を足すのが実運用の基本です。
AI に次のように聞くと、一気に雛形が手に入ります。
先ほどの
notesテーブルに、insert・update・delete それぞれについて「自分の行にだけ作用できる」RLS policy を追加してください。insert はauth.uid() = user_idを with check 条件にしてください。
手順4: 本当に効いているかを確認する
policy は書けても「効いているか」を確かめないと安心できません。次の2つを必ずやってください。
- 自分でログインして、自分の行が見えるか確認する
アプリ側でnotesを取得し、自分が作ったデータが表示されれば OK。 - 別のユーザーでログインし直して、相手の行が見えないことを確認する
テスト用にもう1アカウント作っておき、そのアカウントで開くと空のリストになるはずです。スクリーンショットを2枚残しておくとレビューが楽になります。
もし時間がなければ、Supabase ダッシュボードの「SQL Editor」で次の1行を実行し、自分のトークンで返ってくる行数を確認するだけでも検証になります。
select count(*) from notes;
期待値は「自分が作った行数と一致する」です。別アカウントで実行して 0 に変わることまで見られたら満点です。
つまずきやすいポイント
- RLS を有効にしただけで止めてしまう: policy を1本も書いていないと、アプリ側から何も取れません。取得が急に 0 件になったらまずこれを疑ってください。
- policy は書いたが
user_id列が空のまま: 過去のテストデータにuser_idが入っていないと、それらは誰にも見えなくなります。古いテストデータは消すか、正しい UUID を入れ直します。 - anon key と service role key を取り違える: アプリは必ず anon key(=一般公開用の鍵)を使ってください。service role key(=管理者用の鍵)は RLS を素通りするので、これでテストすると「policy が効いていないように見える」落とし穴があります。
- 自分は動いているから OK と判断してしまう: 必ず 2人目のユーザーで試す。郵便受けの鍵がかかっているかは、他人の鍵で開かないことで初めて確認できます。
完了の合図
次の3つが揃えばこの Atom は完了です。
notes(または相当するテーブル)に RLS が有効になっている- SELECT / INSERT / UPDATE / DELETE に対応する policy が、少なくとも自分の行に作用する形で存在する
- 自分のアカウントでは自分の行だけ見え、他アカウントでは見えないことをスクリーンショット2枚で残せた
種類: code_snippet
検証: basic_manual_check_v1
証跡証跡成果物が正しく作れたことを確認するためのチェックリストです(例: ブラウザで動作する、フォーム送信で値が保存される)。
メディア