Corak RLS Supabase Multi-Tenant untuk Aplikasi SaaS Malaysia
Panduan enam corak RLS Supabase multi-tenant yang kami guna di JRV Systems untuk melindungi data. Belajar cara mengasingkan penyewa, urus peranan, dan uji polisi.
Di JRV Systems, kami membina aplikasi SaaS multi-tenant untuk perniagaan di Malaysia, daripada sistem pengurusan klinik sehinggalah platform pengebilan khas. Cabaran utama dalam mana-mana seni bina multi-tenant ialah pengasingan data: memastikan Klinik A tidak boleh melihat rekod pesakit Klinik B.
Supabase menawarkan alat yang hebat untuk tujuan ini yang dipanggil Row Level Security (RLS), yang menguatkuasakan peraturan akses data terus di dalam pangkalan data. Melalui beberapa projek, kami telah membangunkan satu set corak RLS Supabase multi-tenant yang boleh dipercayai. Ini bukan konsep teori; ia adalah polisi yang telah diuji dan digunakan dalam persekitaran produksi. Menggunakan RLS dengan betul dari awal dapat mengelakkan logik kebenaran yang rumit dan mudah ralat dalam kod aplikasi anda.
Corak Teras untuk Pengasingan Penyewa dan Pengguna
Ini adalah polisi asas yang diperlukan oleh kebanyakan aplikasi multi-tenant. Ia memastikan data diasingkan dengan ketat antara penyewa yang berbeza (contohnya, syarikat, klinik) dan pengguna dalam satu penyewa hanya boleh mengakses data mereka sendiri.
-
Pengasingan Penyewa melalui JWT Claim: Ini adalah corak yang paling kritikal. Apabila pengguna log masuk, kami memasukkan
tenant_idmereka ke dalam JSON Web Token (JWT). Supabase memudahkannya dengan menggunakan 'claim' khas dalamapp_metadata. Polisi RLS kemudiannya akan menyemak 'claim' ini untuk setiap pertanyaan pangkalan data. Polisi biasa untuk jadualpatientsakan kelihatan seperti ini:(SELECT app_metadata ->> 'tenant_id' FROM auth.users WHERE id = auth.uid())::uuid = tenant_id. Ini memastikan pertanyaan pengguna ditapis secara automatik mengikut data penyewa mereka, tanpa risiko kebocoran data antara penyewa. -
Pemilikan Baris melalui
auth.uid(): Dalam sesebuah penyewa, anda sering perlu mengehadkan akses kepada baris tertentu. Contohnya, seorang doktor hanya patut melihat nota konsultasi yang diciptanya. Kami menguruskannya dengan menambah lajurowner_id(ataucreated_by) pada jadual, yang menyimpan UUID pengguna. Polisi RLSnya ringkas dan cekap:auth.uid() = owner_id. Ini membenarkan pengguna untukSELECT,UPDATE, danDELETErekod mereka sendiri. -
Akses Berasaskan Peranan melalui Jadual Graf: Pemilikan ringkas tidak selalunya mencukupi. Seorang pengurus klinik perlu melihat semua rekod untuk kliniknya, bukan hanya miliknya. Kami melaksanakannya dengan jadual
user_rolesyang menghubungkanuser_id,tenant_id, danrole(cth., 'admin', 'doktor'). Polisi RLS kemudiannya boleh menyemak peranan tertentu:EXISTS (SELECT 1 FROM user_roles WHERE user_id = auth.uid() AND role = 'admin'). Ini lebih fleksibel daripada menyimpan peranan terus dalam jadualauth.users, kerana ia membenarkan pengguna mempunyai peranan yang berbeza dalam penyewa yang berbeza.
Corak Lanjutan untuk Senario Khusus
Setelah pengasingan teras dilaksanakan, anda sering menghadapi keperluan yang lebih terperinci. Corak-corak ini menangani logik perniagaan biasa seperti 'soft delete' dan jejak audit.
-
Menyekat Akses kepada Rekod 'Soft-Delete': Kami jarang memadam data secara kekal. Sebaliknya, kami menggunakan lajur cap masa
deleted_at. Secara lalai, pengguna tidak sepatutnya melihat rekod yang telah di-'soft-delete' ini. Kami menambahdeleted_at IS NULLpada polisiSELECTkami. Walau bagaimanapun, seorang admin mungkin perlu melihat atau memulihkannya. Untuk ini, kami mencipta polisi berasingan untuk peranan 'admin' yang tidak menyertakan semakandeleted_at IS NULL, memberikan mereka penglihatan penuh. -
Polisi Baca Sahaja untuk Jejak Audit: Untuk jadual seperti
audit_logs, tiada pengguna yang sepatutnya boleh mengubah suai atau memadam rekod selepas ia dicipta. Kami melaksanakannya dengan persediaan RLS yang ketat. PolisiINSERTmungkin permisif (true), tetapi polisiUPDATEdanDELETEditetapkan secara eksplisit kepadafalse. Ini menjadikan jadual tersebut sebagai log 'append-only' di peringkat pangkalan data, memberikan jaminan integriti data yang kukuh.
Cara Kami Menguji Polisi RLS Sebelum Pelaksanaan
Menulis polisi RLS hanyalah separuh jalan; mengujinya adalah amat penting. Kesilapan boleh membawa kepada pelanggaran data yang serius. Kami sangat bergantung pada Supabase CLI dan ciri ujian pangkalan datanya.
Proses kami melibatkan penciptaan fail seed.sql yang mengisi pangkalan data tempatan dengan data ujian yang realistik untuk pelbagai penyewa dan pengguna dengan peranan yang berbeza. Kemudian, kami menulis ujian pgTAP. Di dalam ujian, anda boleh menyamar sebagai pengguna dan peranan tertentu untuk mengesahkan bahawa polisi berfungsi seperti yang diharapkan.
Sebagai contoh, satu ujian boleh menjalankan pertanyaan sebagai 'user_A' dari 'tenant_1' dan mengesahkan bahawa mereka hanya menerima rekod milik 'tenant_1'. Kemudian, ia boleh menjalankan pertanyaan yang sama sebagai 'user_B' dari 'tenant_2' dan memeriksa skop data mereka. Ujian automatik ini memberi kami keyakinan tinggi bahawa corak RLS Supabase multi-tenant kami dilaksanakan dengan betul sebelum kami melancarkannya ke produksi.
Dengan membina keselamatan terus ke dalam lapisan pangkalan data dengan corak RLS ini, kami mencipta aplikasi SaaS yang lebih mantap dan mudah diselenggara. Logiknya berpusat, dikuatkuasakan secara konsisten, dan kurang terdedah kepada pepijat yang boleh timbul daripada semakan kebenaran yang bertaburan dalam kod aplikasi.