← กลับไปหน้าบทความ
ขั้นสูง (MarTech)

เปิด Database ให้ Frontend เรียกตรงได้ยังไงโดยไม่มีใครขโมยข้อมูลคนอื่นได้

ทีมบรรณาธิการ linli12 ส.ค. 04:52อัปเดต 12 ส.ค. 04:52อ่าน 5 นาที
เปิด Database ให้ Frontend เรียกตรงได้ยังไงโดยไม่มีใครขโมยข้อมูลคนอื่นได้
บทความนี้จัดทำเพื่อความรู้ ชื่อธุรกิจ ตัวเลข หรือบทสนทนาที่ไม่มีแหล่งอ้างอิงกำกับเป็นกรณีตัวอย่างเพื่ออธิบายแนวคิด ดูรายละเอียดที่ นโยบายกองบรรณาธิการ

สรุปสั้น ๆ

Row Level Security หรือ RLS คือกลไกของ Postgres ที่ Supabase เปิดใช้เป็นค่าตั้งต้นสำหรับตารางใหม่ ทำให้ database ตรวจสอบสิทธิ์การเข้าถึงข้อมูลเป็นรายแถวโดยอัตโนมัติทุกครั้งที่มี query เข้ามา ไม่ว่าจะมาจาก frontend โดยตรงหรือจากฝั่งเซิร์ฟเวอร์ ถ้าไม่เปิด RLS หรือเขียน policy ไม่ครบ การให้ frontend เรียกฐานข้อมูลตรงจะเสี่ยงข้อมูลรั่วสูงมาก

หนึ่งในสิ่งที่ทำให้นักพัฒนาที่มาจากสาย backend ดั้งเดิมรู้สึกไม่สบายใจตอนเริ่มใช้ Supabase คือแนวคิดที่ให้ frontend เรียกฐานข้อมูลได้เกือบตรง ๆ ผ่าน client library โดยไม่ต้องผ่าน API layer ที่เขียนเองทั้งหมดเหมือนสถาปัตยกรรมแบบเดิม ความรู้สึกแรกที่หลายคนมีคือ 'แบบนี้ไม่อันตรายเหรอ ใครก็เปิด browser console แล้ว query อะไรก็ได้'

คำตอบคือถ้าไม่มีกลไกป้องกันที่ถูกต้อง มันอันตรายจริงตามที่กังวล แต่ Supabase แก้ปัญหานี้ด้วยการใช้ฟีเจอร์ Row Level Security ที่มีอยู่ในตัว Postgres เองอยู่แล้ว ไม่ใช่ฟีเจอร์ที่ Supabase สร้างขึ้นมาใหม่ เพียงแต่ Supabase ทำให้มันเปิดใช้งานเป็นค่าเริ่มต้นและมี dashboard ให้จัดการง่ายขึ้น

บทความนี้จะอธิบายว่า RLS ทำงานยังไงในทางเทคนิค ทำไมการเปิด Database ให้ frontend เรียกตรงถึงยังปลอดภัยได้ถ้าเขียน policy ถูกต้อง และข้อผิดพลาดที่พบบ่อยที่สุดเมื่อทีมเริ่มเขียน RLS policy ครั้งแรก

Row Level Security คืออะไร ต่างจากการตรวจสิทธิ์แบบเดิมยังไง

ระบบตรวจสิทธิ์แบบดั้งเดิมส่วนใหญ่ทำงานที่ชั้น API เช่น เขียนโค้ด backend ตรวจว่า user คนนี้มีสิทธิ์ดูข้อมูลแถวนี้ไหมก่อนจะ query แล้วส่งผลลัพธ์กลับ วิธีนี้ต้องเขียนการตรวจสอบซ้ำในทุก endpoint ที่แตะข้อมูลชุดเดียวกัน ถ้าลืมตรวจสอบใน endpoint ใดสักจุดหนึ่ง ข้อมูลก็รั่วได้ทันที

RLS ย้ายการตรวจสอบสิทธิ์นี้ลงไปอยู่ในตัวฐานข้อมูลเอง โดยกำหนด policy ไว้ที่ระดับตาราง แล้ว Postgres จะกรองแถวข้อมูลให้อัตโนมัติตาม policy นั้นทุกครั้งที่มี query เข้ามา ไม่ว่า query นั้นจะมาจากไหนก็ตาม ไม่ว่าจะเป็น frontend เรียกตรง, Edge Functions, หรือ backend เดิมที่มีอยู่แล้ว

ข้อดีของแนวทางนี้คือไม่มีทางลืมตรวจสอบสิทธิ์ในบาง endpoint เพราะการตรวจสอบไม่ได้ผูกกับ endpoint แต่ผูกกับตารางข้อมูลโดยตรง ตราบใดที่ policy เขียนถูกต้อง ทุกช่องทางที่เข้าถึงตารางนั้นจะถูกกรองเหมือนกันหมด

เปิด RLS บนตารางที่มี query ใช้งานอยู่แล้ว เกิดอะไรขึ้นทันทีที่กดปุ่ม

คำสั่งเปิด RLS เขียนสั้นมากแค่ ALTER TABLE ตามด้วยชื่อตาราง แล้วต่อด้วย ENABLE ROW LEVEL SECURITY เท่านั้น แต่ผลที่เกิดขึ้นทันทีหลังรันคำสั่งนี้กับตารางที่มี query ใช้งานจริงอยู่แล้ว สำคัญกว่าความยาวของคำสั่งมาก เพราะ Postgres จะเปลี่ยนพฤติกรรมของตารางนั้นทันทีในวินาทีที่รันเสร็จ ไม่ต้อง deploy โค้ดใหม่ ไม่ต้อง restart เซิร์ฟเวอร์ใด ๆ ทั้งสิ้น

ถ้าตารางนั้นยังไม่มี policy อะไรเลยตอนที่เปิด RLS query ที่มาจาก anon key หรือ authenticated key ซึ่งก็คือ query ที่ frontend ยิงตรงผ่าน client library จะเปลี่ยนจากเห็นข้อมูลครบทุกแถวไปเป็นไม่เห็นอะไรเลยทันที ไม่ใช่ error แต่คืนค่าว่างเปล่าแบบเงียบ ๆ ซึ่งอันตรายกว่าการ error ตรงที่หน้าเว็บอาจดูเหมือนใช้งานได้ปกติ เพียงแต่ทุกหน้าที่เคยมีข้อมูลกลับกลายเป็นว่างเปล่าไปเฉย ๆ จนกว่าจะมีคนสังเกตเห็นความผิดปกติ

จุดที่ทำให้หลายทีมงงคือ query ที่รันผ่าน service_role key ในฝั่งเซิร์ฟเวอร์หรือรันผ่าน SQL editor ของ dashboard จะยังคงเห็นข้อมูลครบเหมือนเดิมทุกประการ เพราะ service_role bypass RLS ไปเลยไม่ว่าจะมี policy หรือไม่ ผลคือถ้าทีมทดสอบด้วยการรัน query ผ่าน dashboard หรือผ่านสคริปต์ที่ใช้ service_role key แล้วสรุปว่าใช้งานได้ปกติ ทั้งที่ยังไม่ได้เขียน policy เลยสักตัว พอ frontend จริงเรียกด้วย anon key จะพังทันทีโดยที่ฝั่งทดสอบไม่เคยเห็นปัญหานี้มาก่อนเลย

แนวทางที่ปลอดภัยกว่าคือเปิด RLS กับเขียน policy พร้อมกันในการ deploy รอบเดียวกันเสมอ ไม่ใช่เปิด RLS ไว้ก่อนแล้วค่อยตามด้วย policy ทีหลังเป็นคนละรอบ เพราะช่วงเวลาระหว่างสองขั้นตอนนั้น ถ้าเป็นตารางที่มีผู้ใช้งานจริงอยู่แล้ว ผู้ใช้จะเจอหน้าจอว่างเปล่าโดยไม่มีคำเตือนใด ๆ ล่วงหน้า และทีม support มักจะเป็นฝ่ายที่รู้ปัญหาก่อนทีมพัฒนาเสียอีก

USING กับ WITH CHECK ต่างกันตรงไหน ลืมตัวไหนแล้วเสี่ยงข้อมูลหลุด

policy หนึ่งอันมีสองส่วนเงื่อนไขที่ทำหน้าที่ต่างกันคือ USING กับ WITH CHECK แม้หน้าตาจะดูคล้ายกันเพราะเป็นนิพจน์ SQL แบบเดียวกัน แต่จุดที่ใช้ตรวจสอบต่างกันโดยสิ้นเชิง USING ใช้ตรวจแถวที่มีอยู่แล้วในตาราง ว่ามองเห็นได้ไหมสำหรับ SELECT หรือแก้ไข/ลบได้ไหมสำหรับ UPDATE และ DELETE ส่วน WITH CHECK ใช้ตรวจแถวใหม่ที่กำลังจะถูกเขียนเข้าไป ว่าค่าที่จะบันทึกนั้นผ่านเงื่อนไขหรือไม่ สำหรับ INSERT และ UPDATE

ตัวอย่าง SQL ที่แสดงความต่างชัดเจนคือสองบรรทัดนี้ (ตัวอย่างประกอบการอธิบาย ไม่ใช่โค้ด production): CREATE POLICY read_own ON projects FOR SELECT USING (organization_id = current_org_id()) กับ CREATE POLICY insert_own ON projects FOR INSERT WITH CHECK (organization_id = current_org_id()) จะเห็นว่า policy แรกใช้ USING เพราะเป็นการกรองแถวที่มีอยู่แล้วตอนอ่าน ส่วน policy ที่สองใช้ WITH CHECK เพราะเป็นการตรวจแถวใหม่ตอนเขียน ทั้งสองแบบต้องเขียนแยกกันเพราะ INSERT ไม่มีแถวเก่าให้ USING ตรวจสอบได้เลย

ปัญหาจริงที่พบบ่อยเกิดตอนทีมเขียน policy สำหรับ INSERT แยกออกมาต่างหาก แล้วตั้ง WITH CHECK หลวมกว่า policy SELECT ที่ใช้ USING กรองเข้มงวด เช่นเขียน WITH CHECK (true) เพื่อให้ INSERT ผ่านง่าย ๆ ตอนพัฒนา โดยตั้งใจว่าจะกลับมาแก้ทีหลังแล้วลืมไป ผลคือผู้ใช้สามารถ insert แถวที่มี organization_id ผิดจากขององค์กรตัวเองได้สำเร็จ เพราะ WITH CHECK ไม่ได้ตรวจสอบอะไรเลย แต่พอ query กลับมาดูแถวเดียวกัน SELECT policy จะกรองแถวนั้นออกไปทันทีเพราะ organization_id ไม่ตรงเงื่อนไข กลายเป็นว่าข้อมูลถูกสร้างขึ้นจริงในตารางแล้ว แต่ผู้ใช้เองกลับหาไม่เจอ ทำให้ทีม debug ผิดทางไปนึกว่า insert ไม่สำเร็จหรือข้อมูลหาย ทั้งที่จริงมันอยู่ในตารางแล้วแค่ policy การอ่านมองไม่เห็นเท่านั้นเอง

ตารางด้านล่างสรุปว่าแต่ละ operation ใช้เงื่อนไขไหนตรวจสอบบ้าง เพื่อให้เวลาเขียน policy ใหม่ไม่ลืมใส่ให้ครบ และตั้งความเข้มงวดของ WITH CHECK ให้ไม่หลวมกว่า USING ของ policy อ่านเสมอ:

Operationใช้ USINGใช้ WITH CHECKตรวจอะไร
SELECTใช้ไม่ใช้กรองว่าแถวที่มีอยู่มองเห็นได้ไหม
INSERTไม่ใช้ใช้ตรวจว่าแถวใหม่ที่จะสร้างผ่านเงื่อนไขไหม
UPDATEใช้ใช้USING กรองแถวเก่าที่แก้ได้ WITH CHECK ตรวจค่าใหม่หลังแก้
DELETEใช้ไม่ใช้กรองว่าแถวไหนลบได้

Policy ถูกตรวจสอบตอนไหน และใช้ข้อมูลอะไรตัดสิน

ทุกครั้งที่มี query เข้ามาที่ตารางซึ่งเปิด RLS ไว้ Postgres จะรันเงื่อนไขใน policy ก่อนคืนผลลัพธ์ โดยปกติเงื่อนไขจะอ้างอิงค่า auth.uid() ซึ่งเป็นฟังก์ชันที่ Supabase เตรียมไว้ให้ดึงค่า user id จาก JWT ที่แนบมากับ request นั้น เชื่อมโยงกับระบบยืนยันตัวตนที่อธิบายไว้ในบทความ Supabase Auth คืออะไร

ตัวอย่าง policy พื้นฐานที่สุดคือ อนุญาตให้ผู้ใช้อ่านเฉพาะแถวที่คอลัมน์ user_id ตรงกับ auth.uid() ของตัวเอง เขียนเป็นเงื่อนไข SQL ง่าย ๆ แล้วผูกกับคำสั่ง SELECT, INSERT, UPDATE หรือ DELETE แยกกันได้ตามต้องการ ไม่จำเป็นต้องใช้เงื่อนไขเดียวกันทุกคำสั่ง

จุดที่ต้องเข้าใจให้ชัดคือ policy แต่ละอันผูกกับ operation เฉพาะ ถ้าเปิด RLS แล้วแต่ไม่มี policy สำหรับ operation ไหนเลย operation นั้นจะถูกปฏิเสธทั้งหมดเป็นค่าเริ่มต้น ไม่ใช่อนุญาตทั้งหมด นี่คือหลักการ 'ปิดก่อน แล้วค่อยเปิดเฉพาะที่อนุญาต' ซึ่งปลอดภัยกว่าการตั้งต้นแบบเปิดทุกอย่าง

ตัวอย่างสมมติ: เขียน Policy สำหรับระบบ SaaS หลายองค์กร

ลองดูตัวอย่างสมมติของระบบ SaaS ที่มีตาราง projects ซึ่งแต่ละ project เป็นของ organization ใดองค์กรหนึ่ง (ตัวอย่างเพื่อประกอบการอธิบายแนวคิด ไม่ใช่โค้ด production จริง):

  1. เปิด RLS บนตาราง projects ด้วยคำสั่ง ALTER TABLE projects ENABLE ROW LEVEL SECURITY ก่อนเป็นอันดับแรก
  2. เขียน policy สำหรับ SELECT ที่ตรวจสอบว่า organization_id ของแถวนั้นตรงกับ organization ที่ผู้ใช้ปัจจุบันเป็นสมาชิกอยู่ โดย join กับตาราง organization_members ผ่าน subquery
  3. เขียน policy แยกสำหรับ INSERT ที่ตรวจสอบว่า organization_id ที่กำลังจะสร้างข้อมูลใหม่ ตรงกับองค์กรที่ผู้ใช้เป็นสมาชิกและมี role ที่มีสิทธิ์สร้างข้อมูล เช่น owner หรือ admin เท่านั้น ไม่ใช่ทุก role
  4. เขียน policy สำหรับ UPDATE และ DELETE แยกกันอีกชุด เพราะบางระบบอาจอนุญาตให้สมาชิกทั่วไปอ่านได้ แต่แก้ไขหรือลบได้เฉพาะ owner เท่านั้น
  5. ทดสอบด้วยการสร้างผู้ใช้ทดสอบหลายคนในหลายองค์กร แล้วลอง query ด้วยแต่ละบัญชีจริง เพื่อยืนยันว่าเห็นเฉพาะข้อมูลขององค์กรตัวเองเท่านั้น ไม่ใช่แค่ทดสอบแบบอ่าน policy ผ่านสายตาอย่างเดียว

service_role key ข้าม RLS ได้ ต้องระวังยังไง

มีจุดหนึ่งที่ต้องเข้าใจให้ชัดคือ service_role key ที่ Supabase ให้มาสำหรับใช้งานฝั่งเซิร์ฟเวอร์ ข้ามการตรวจสอบ RLS ทุกกฎโดยสมบูรณ์ ออกแบบมาเพื่องานที่ต้องเข้าถึงข้อมูลข้ามผู้ใช้ทุกคน เช่นงานดูแลระบบหรือรายงานสรุป

ปัญหาที่พบบ่อยคือทีมพัฒนาใช้ service_role key ในฟังก์ชันหรือโค้ดที่เปิดให้ client เรียกตรงได้โดยไม่มีการตรวจสอบสิทธิ์เพิ่มเติมเอง เพราะระหว่างพัฒนารู้สึกว่าใช้ key นี้แล้ว query ผ่านง่ายกว่าไม่ติด RLS ให้ปวดหัว แต่พอ deploy ขึ้นจริงกลายเป็นช่องโหว่ใหญ่ที่ใครก็ดึงข้อมูลข้ามผู้ใช้ได้หมด

หลักที่ควรยึดไว้คือ service_role key ใช้ได้เฉพาะในโค้ดฝั่งเซิร์ฟเวอร์ที่ไม่มีทางถูก client เข้าถึงโดยตรง เช่นใน Edge Functions ที่มีการตรวจสอบ JWT และสิทธิ์ของผู้เรียกเองก่อนแล้ว ไม่ใช่ฝัง key นี้ไว้ที่ไหนก็ได้ที่สะดวก

RLS กระทบ performance ไหม ควรออกแบบยังไงให้เร็ว

คำถามที่พบบ่อยคือ RLS ทำให้ query ช้าลงหรือเปล่า เพราะทุก query ต้องผ่านการตรวจสอบเงื่อนไขเพิ่ม คำตอบคือมีผลกระทบจริงแต่ควบคุมได้ ถ้าเงื่อนไขใน policy ซับซ้อนเกินไป เช่นมี subquery ซ้อนหลายชั้น หรือ join ตารางใหญ่โดยไม่มี index รองรับ query อาจช้าลงอย่างมีนัยสำคัญเมื่อข้อมูลเยอะขึ้น

วิธีที่ช่วยได้มากคือสร้าง index บนคอลัมน์ที่ policy ใช้ตรวจสอบเป็นประจำ เช่น organization_id หรือ user_id เพราะ policy จะถูกรันแทบทุก query ที่แตะตารางนั้น การมี index ที่เหมาะสมช่วยลดเวลาตรวจสอบได้มาก

อีกเทคนิคที่ช่วยได้คือเขียน policy ให้ใช้ auth.uid() เทียบตรง ๆ กับคอลัมน์ในตารางแทนการ join ซับซ้อนถ้าทำได้ เช่น เก็บ organization_id ไว้ในตาราง profile ของผู้ใช้แต่ละคนแทนการต้อง join ผ่านตารางกลางทุกครั้ง จะช่วยให้ query เร็วขึ้นเมื่อระบบมีข้อมูลจำนวนมาก

ทดสอบ RLS ยังไงให้มั่นใจก่อนขึ้น production

การเขียน policy ผิดแม้แค่นิดเดียวอาจทำให้ข้อมูลรั่วทั้งระบบ ดังนั้นการทดสอบต้องทำอย่างจริงจัง ไม่ใช่แค่ลอง query ด้วยบัญชีของตัวเองแล้วดูว่าใช้งานได้ก็จบ

  • สร้างบัญชีทดสอบอย่างน้อยสององค์กรที่มีข้อมูลแยกกันชัดเจน แล้วสลับล็อกอินไปมาเพื่อยืนยันว่าแต่ละบัญชีเห็นเฉพาะข้อมูลของตัวเอง
  • ทดสอบทั้งสี่ operation คือ SELECT, INSERT, UPDATE, DELETE แยกกัน เพราะ policy แต่ละตัวเป็นอิสระต่อกัน ผ่านตัวหนึ่งไม่ได้แปลว่าอีกตัวถูกต้องด้วย
  • ทดสอบกรณี edge case เช่น ผู้ใช้ที่ไม่ได้เป็นสมาชิกองค์กรไหนเลย หรือผู้ใช้ที่เพิ่งถูกลบออกจากทีม ว่ายังเข้าถึงข้อมูลเก่าได้อยู่หรือไม่
  • เขียน automated test สำหรับ policy สำคัญไว้เป็นส่วนหนึ่งของ CI เพื่อจับความผิดพลาดตั้งแต่ตอนแก้ policy ในอนาคต ไม่ใช่พึ่งพาการทดสอบด้วยมือทุกครั้ง

ทำแบบนี้แล้วพัง เพราะอะไร

สรุปข้อผิดพลาดที่พบบ่อยที่สุดเมื่อทีมเริ่มใช้ RLS ครั้งแรก:

  • สร้างตารางใหม่แล้วลืมเปิด RLS — ตารางที่ไม่เปิด RLS จะเปิดให้ query ได้แบบไม่มีการกรองเลยถ้าใช้ role ที่มีสิทธิ์เพียงพอ ควรตั้งเป็นขั้นตอนบังคับทุกครั้งที่สร้างตารางใหม่
  • เปิด RLS แต่ไม่เขียน policy ให้ครบทุก operation — ทำให้ operation ที่ไม่มี policy ถูกปฏิเสธหมด ผู้ใช้งานจริงเจอ error โดยไม่รู้สาเหตุ
  • ใช้ service_role key ในโค้ดที่ client เรียกถึงได้ — เปิดช่องให้ทุกคนข้าม RLS ได้ทั้งระบบ
  • เขียน policy ซับซ้อนเกินจำเป็นโดยไม่มี index รองรับ — ทำให้ query ช้าลงมากเมื่อข้อมูลเติบโต

สรุป

การให้ frontend เรียกฐานข้อมูลตรงไม่ใช่เรื่องอันตรายในตัวมันเอง ถ้ามีกลไกกรองสิทธิ์ที่แข็งแรงพออย่าง Row Level Security คอยทำงานอยู่เบื้องหลังทุก query สิ่งที่ทีมพัฒนาต้องรับผิดชอบคือเขียน policy ให้ครบทุก operation ทดสอบให้ครอบคลุมทุกบทบาทของผู้ใช้ และระวังการใช้ service_role key ในจุดที่ client เข้าถึงได้

ถ้าเพิ่งเริ่มใช้ RLS แนะนำให้เริ่มจากตารางที่มีความเสี่ยงสูงสุดก่อน เช่นตารางที่เก็บข้อมูลส่วนตัวหรือข้อมูลการเงิน แล้วค่อยขยายไปยังตารางอื่น พร้อมเขียน automated test คู่กันไปทุกครั้งที่แก้ policy เพื่อไม่ให้เผลอเปิดช่องโหว่โดยไม่รู้ตัว

  • RLS ย้ายการตรวจสอบสิทธิ์ลงไปอยู่ในฐานข้อมูล กรองทุก query ไม่ว่าจะมาจากช่องทางไหน
  • ปิดก่อนแล้วค่อยเปิดเฉพาะที่อนุญาต คือหลักการเริ่มต้นของ RLS
  • service_role key ข้าม RLS ได้ทั้งหมด ใช้ได้เฉพาะฝั่งเซิร์ฟเวอร์ที่ client เข้าถึงไม่ได้เท่านั้น

คำถามที่พบบ่อย

RLS บังคับใช้กับทุกตารางใน Supabase โดยอัตโนมัติไหม

ตารางที่สร้างผ่าน dashboard ของ Supabase มักถูกเตือนหรือแนะนำให้เปิด RLS แต่ไม่ได้บังคับเปิดอัตโนมัติเสมอไปในทุกกรณี ทีมพัฒนาควรตรวจสอบสถานะ RLS ของทุกตารางที่มีข้อมูลผู้ใช้ก่อนขึ้น production เสมอ

ถ้าลืมเขียน policy ไว้เลย จะเกิดอะไรขึ้น

ถ้าเปิด RLS แล้วไม่มี policy ใด ๆ เลย operation นั้นจะถูกปฏิเสธทั้งหมดเป็นค่าเริ่มต้น ผู้ใช้จะไม่สามารถอ่านหรือเขียนข้อมูลได้เลยแม้จะล็อกอินถูกต้อง ต่างจากการไม่เปิด RLS ที่ปล่อยให้เข้าถึงได้แบบไม่มีการกรอง

เขียน policy ด้วยภาษาอะไร

เขียนด้วย SQL ปกติ โดยใช้เงื่อนไขแบบเดียวกับ WHERE clause ทั่วไป ผูกกับ operation ที่ต้องการควบคุม สามารถเขียนผ่าน SQL editor ใน dashboard หรือผ่านไฟล์ migration ก็ได้

RLS ใช้ร่วมกับ Edge Functions ได้ไหม

ได้ ถ้า Edge Functions เรียกฐานข้อมูลด้วย anon key หรือ key ของผู้ใช้ RLS จะยังทำงานตามปกติ แต่ถ้าใช้ service_role key จะข้าม RLS ไปโดยสมบูรณ์ ต้องเขียนการตรวจสอบสิทธิ์เองในฟังก์ชันแทน

ทดสอบ RLS ด้วยบัญชีแอดมินคนเดียวพอไหม

ไม่พอ เพราะบัญชีแอดมินมักมีสิทธิ์กว้างกว่าผู้ใช้ทั่วไป ต้องทดสอบด้วยบัญชีที่มีบทบาทหลากหลายและอยู่คนละองค์กร เพื่อยืนยันว่าการกรองข้อมูลทำงานถูกต้องในทุกสถานการณ์จริง

RLS ป้องกัน SQL Injection ได้ไหม

ไม่ได้โดยตรง RLS ทำหน้าที่กรองว่าใครเห็นแถวไหนได้บ้าง แต่การป้องกัน SQL Injection ยังต้องพึ่งพาการใช้ parameterized query หรือ client library ที่ escape ค่าอินพุตให้ถูกต้องอยู่ดี ทั้งสองเรื่องเป็นคนละชั้นของความปลอดภัย

วัด Conversion LINE ทุกแบรนด์ รวมศูนย์ที่เดียว

องค์กรที่มีหลายแบรนด์ หลายสาขา หลาย LINE OA — linli รวม Tracking และส่ง Conversion กลับทุกแพลตฟอร์ม พร้อม Custom Limit เริ่มฟรี 14 วัน

ติดต่อทีม Sales

บทความที่เกี่ยวข้อง

แชทสดหรือแดชบอร์ดที่อัปเดตเองต้องใช้ Supabase Realtime เมื่อไหร่ ไม่ใช่ทุกโปรเจกต์

แชทสดหรือแดชบอร์ดที่อัปเดตเองต้องใช้ Supabase Realtime เมื่อไหร่ ไม่ใช่ทุกโปรเจกต์

หลายทีมเปิด Supabase Realtime ทันทีที่เห็นว่ามีให้ใช้ โดยไม่ได้ประเมินว่าโปรเจกต์ตัวเองต้องการจริงไหม บทความนี้ชี้เงื่อนไขว่าเมื่อไรใช้ Realtime คุ้มค่า และเมื่อไรควรใช้ polling ธรรมดาแทน
ทดสอบ schema ใหม่บน production ตรง ๆ ได้ไหมหรือต้องแยก branch ก่อนเสมอ

ทดสอบ schema ใหม่บน production ตรง ๆ ได้ไหมหรือต้องแยก branch ก่อนเสมอ

ทีมพัฒนาหลายทีมยังแก้ schema production ตรง ๆ เพราะไม่รู้ว่า Supabase มีฟีเจอร์ branching ให้แยกฐานข้อมูลทดสอบออกจากของจริงได้ บทความนี้อธิบายว่า branching ทำงานยังไงและช่วยลดความเสี่ยงตรงไหนบ้าง
ทีมเล็กที่ยังไม่มี DevOps ควรลงมือกับ Cloudflare Workers ตอนไหนถึงจะคุ้ม

ทีมเล็กที่ยังไม่มี DevOps ควรลงมือกับ Cloudflare Workers ตอนไหนถึงจะคุ้ม

Cloudflare Workers ไม่ใช่คำตอบสำหรับทุกงาน แต่สำหรับ API ที่ต้องตอบเร็วในหลายภูมิภาคหรือ Webhook ที่รับทราฟฟิกไม่แน่นอน มันแก้ปัญหาที่ Server แบบเดิมแก้ได้ยาก บทความนี้ชี้ชัดว่าเมื่อไรควรใช้และเมื่อไรยังไม่จำเป็น