Supabaseの行セキュリティを「ポリシーなし」にして、サーバーだけが読み書きする設計にした理由
結論から書く。一人で使う個人のアプリでは、Supabaseの行セキュリティ(RLS)をオンにしたまま、ポリシーを1つも作らない設計にした。ブラウザからは何も読めず、何も書けない。読み書きは全部、本人かどうかを確かめたあとのサーバーの処理だけが行う。
この形にしたのは、AIに作らせた最初の版で、ログインの確認が実質ないのと同じ状態になっていたからだ。直すときに、「どこで止めるか」を一か所にまとめたかった。
1|最初の版で起きていたこと
AIが作った最初の版は、画面を出す前に「ログインの印があるか」だけを見ていた。中身が本物かどうかは確かめていない。データベースの側も、「ログインしている人なら全部できる」に近い作りだった。
これだと、守りが2か所あるように見えて、どちらも薄い。どちらか片方を直しても、もう片方から通れてしまう。
2|ポリシーなしにすると、どうなるか
Supabaseの行セキュリティは、オンにするとポリシーで許したことしかできなくなる。ポリシーを1つも作らなければ、ブラウザに渡している公開用の鍵では、何もできない。
・読もうとすると、空の一覧が返る
・書こうとすると、断られる
一方、サーバーには、行セキュリティを通らない強い鍵を置く。この鍵はブラウザに出さない。サーバーの処理は、次の順で動く。
・まず、ログインしているのが本人か(決めておいた1つのメールアドレスか)を確かめる
・本人なら、強い鍵でデータベースを読み書きする
・本人でなければ、何もせずに断る
止める場所は、サーバーの入り口の1か所だけになった。
これは、AIに直させるときにも効く。新しい画面や機能を頼むとき、「データを読むなら、必ずサーバーの処理を通し、最初に本人の確認をする」とだけ伝えればいい。AIが作ったものを見直すときも、本人の確認が入り口にあるかどうかを見るだけで済む。守りが何か所にも散っていると、どこか1つの抜けを、毎回探すことになる。
3|「ログインしていれば全部できる」に戻さない
最初の版には、「ログインしている人には全部の操作を許す」形の作りが入っていた。画面から直接データを読めると、作るのが楽になるからだ。AIは、楽な方を選びやすい。
だから、直したあとで、作業の決まりとして書いておいた。行セキュリティやログインを触るときは、そのポリシーに戻さない。一人で使うアプリでも、ログインできる人が増えたとき(間違ってほかのアドレスでログインしたときも含む)に、全部が見えてしまうからだ。
4|外から確かめる
作ったあとは、必ず外から確かめる。ブラウザと同じ公開用の鍵を使って、データベースを直接叩く。
・新しく作った表を読む → 空の一覧が返ること
・同じ表に書く → 断られること
新しい表を足すたびに、この2つを見る。表を作るときに行セキュリティをオンにし忘れると、公開用の鍵で読めてしまう。忘れていないかを、目で見るのではなく、実際に叩いて確かめる。
5|この設計の弱いところ
いいことばかりではない。
・ブラウザから直接データを読めないので、全部の画面にサーバーの処理が要る
・データが変わったらすぐ画面に出す仕組み(ブラウザからの購読)は、そのままでは使えない
・サーバーの強い鍵が漏れたら、全部が終わる。だから、鍵は秘密の置き場に入れ、画面やログに出さない
一人で使う、画面の数も多くないアプリなら、これで足りている。
まとめ
・行セキュリティはオン、ポリシーはなし。ブラウザからは読めず、書けない
・読み書きは、本人を確かめたあとのサーバーだけが行う
・「ログインしていれば全部できる」に戻さない
・新しい表を作ったら、公開用の鍵で叩いて、空の一覧と、断られることを確かめる
守る場所を増やすより、1か所にまとめて、そこを外から確かめる方が、AIと一緒に作るときは迷わない。