SQL Academy · บทเรียน

นโยบายความปลอดภัยระดับแถว

กรองแถวตามผู้ใช้โดยอัตโนมัติ

บทเรียน 2 จาก 413 ขั้นตอน

นโยบายความปลอดภัยระดับแถว เป็นบทเรียน SQL Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน SQL Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

ความปลอดภัยระดับแถวคืออะไร

ความปลอดภัยระดับแถว (RLS) เป็นฟีเจอร์ของ PostgreSQL ที่ช่วยให้คุณควบคุมได้ว่าผู้ใช้หรือบทบาทของฐานข้อมูลแต่ละรายจะมองเห็นหรือแก้ไขแถวใดของตารางได้บ้าง แทนที่จะกรองแถวในทุกคำสั่งค้นหา คุณสามารถกำหนดนโยบายเพียงครั้งเดียว แล้ว PostgreSQL จะบังคับใช้นโยบายนั้นโดยอัตโนมัติกับทุกคำสั่ง SELECT, INSERT, UPDATE และ DELETE

ลองนึกภาพว่านี่คือส่วนคำสั่ง WHERE ที่มองไม่เห็น ซึ่งติดอยู่กับตัวตารางเองแทนที่จะติดอยู่กับคำสั่งค้นหาใดคำสั่งหนึ่ง

การเปิดใช้ RLS บนตาราง

RLS ถูกปิดใช้งานไว้โดยค่าเริ่มต้น คุณต้องเปิดใช้โดยเฉพาะสำหรับแต่ละตารางด้วย ALTER TABLE ... ENABLE ROW LEVEL SECURITY เมื่อเปิดใช้แล้ว บทบาทใดก็ตามที่ไม่ใช่เจ้าของตารางจะมองไม่เห็นแถวใด ๆ จนกว่าจะมีการสร้างนโยบายอย่างน้อยหนึ่งรายการ

-- Create a sample table
CREATE TABLE orders (
  id        SERIAL PRIMARY KEY,
  owner     TEXT NOT NULL,
  amount    NUMERIC(10,2)
);

-- Enable RLS
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

การสร้างนโยบายแรกของคุณ

นโยบายถูกสร้างด้วย CREATE POLICY คุณตั้งชื่อให้กับนโยบาย ระบุตาราง และจัดเตรียมนิพจน์ USING ส่วนคำสั่ง USING คือนิพจน์บูลีนที่ประเมินกับแต่ละแถว — ผู้ใช้จะมองเห็นเฉพาะแถวที่นิพจน์ให้ผลเป็น TRUE เท่านั้น

-- Allow each user to see only their own orders
CREATE POLICY orders_owner_policy
  ON orders
  FOR SELECT
  USING (owner = current_user);

อนุประโยค USING กับ WITH CHECK

นโยบายมีเงื่อนไขการกรองสองแบบซึ่งมีจุดประสงค์แตกต่างกัน:

  • USING — กรองแถวในการดำเนินการอ่านข้อมูล (SELECT, UPDATE, DELETE) แถวจะแสดงให้เห็นได้ก็ต่อเมื่อ USING ให้ผลเป็น TRUE
  • WITH CHECK — ตรวจสอบแถวในการดำเนินการเขียนข้อมูล (INSERT, UPDATE) การเขียนข้อมูลจะทำได้ก็ต่อเมื่อ WITH CHECK ให้ผลเป็น TRUE หากไม่ระบุไว้ ระบบจะนำ USING มาใช้ตรวจสอบการเขียนข้อมูล
-- Allow users to select and insert only their own rows
CREATE POLICY orders_isolation
  ON orders
  FOR ALL
  USING       (owner = current_user)
  WITH CHECK  (owner = current_user);

ขอบเขตของนโยบาย: FOR SELECT, INSERT, UPDATE, DELETE

นโยบายเดียวสามารถครอบคลุมคำสั่งทั้งหมด (FOR ALL) หรือครอบคลุมคำสั่งใดคำสั่งหนึ่งโดยเฉพาะก็ได้ การแยกนโยบายตามคำสั่งช่วยให้ควบคุมได้อย่างละเอียด เช่น อนุญาตให้ผู้ใช้ทุกคนอ่านได้ทุกแถว แต่แก้ไขได้เฉพาะแถวของตนเอง

-- Everyone can read all orders
CREATE POLICY read_all_orders
  ON orders
  FOR SELECT
  USING (true);

-- But each user can only update their own orders
CREATE POLICY update_own_orders
  ON orders
  FOR UPDATE
  USING       (owner = current_user)
  WITH CHECK  (owner = current_user);

การใช้ผู้ใช้เซสชันและ current_user

PostgreSQL มีฟังก์ชันในตัวสำหรับระบุผู้ใช้ที่กำลังใช้งานอยู่ภายในนิพจน์ของนโยบาย:

  • current_user — บทบาทที่กำลังใช้สิทธิ์อยู่ในขณะนั้น (อาจเปลี่ยนแปลงได้หลัง SET ROLE)
  • ผู้ใช้เซสชัน — บทบาทที่เปิดการเชื่อมต่อ (จะไม่เปลี่ยนแปลงตลอดเซสชัน)

นโยบาย RLS ส่วนใหญ่อาศัย current_user เนื่องจากสะท้อนบทบาทที่มีผลจริงหลังการสลับบทบาท

-- Inspect the current identity inside a query
SELECT current_user, session_user;

การใช้ RLS กับบทบาทเฉพาะ

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

-- Policy only for the 'app_user' role
CREATE POLICY app_user_policy
  ON orders
  FOR SELECT
  TO app_user
  USING (owner = current_user);

-- Separate permissive policy for 'admin' role
CREATE POLICY admin_full_access
  ON orders
  FOR ALL
  TO admin
  USING (true)
  WITH CHECK (true);

นโยบาย PERMISSIVE กับ RESTRICTIVE

นโยบายหลายรายการในตารางเดียวกันสามารถทำงานร่วมกันได้สองรูปแบบ:

  • PERMISSIVE (ค่าเริ่มต้น) — นโยบายแบบ permissive ทั้งหมดจะเชื่อมด้วย OR แถวจะเข้าถึงได้หากมีนโยบายแบบ permissive ใดนโยบายหนึ่งอนุญาต
  • RESTRICTIVE — นโยบายแบบ restrictive จะเชื่อมด้วย AND กับผลลัพธ์จากนโยบายแบบ permissive แถวจะเข้าถึงได้ก็ต่อเมื่อผ่านนโยบายแบบ restrictive และผ่านนโยบายแบบ permissive อย่างน้อยหนึ่งรายการ
-- Restrictive policy: block access to archived orders for everyone
CREATE POLICY no_archived_rows
  ON orders
  AS RESTRICTIVE
  FOR SELECT
  USING (amount > 0);

การข้าม RLS: BYPASSRLS และเจ้าของตาราง

เจ้าของตารางและผู้ใช้ระดับสูงสุดจะข้าม RLS ได้โดยค่าเริ่มต้นและมองเห็นทุกแถวเสมอ คุณสามารถมอบแอตทริบิวต์ BYPASSRLS ให้บทบาทหนึ่งได้ หากบทบาทนั้นต้องการ access แบบไม่จำกัดโดยไม่ต้องเป็นผู้ใช้ระดับสูงสุด ในทางกลับกัน คุณสามารถบังคับให้เจ้าของตารางปฏิบัติตาม RLS ได้โดยใช้ FORCE ROW LEVEL SECURITY

-- Force the table owner to also obey RLS policies
ALTER TABLE orders FORCE ROW LEVEL SECURITY;

-- Grant BYPASSRLS to a trusted service account
ALTER ROLE service_account BYPASSRLS;

การแก้ไขและลบนโยบาย

คุณสามารถแก้ไขนโยบายที่มีอยู่ด้วย ALTER POLICY หรือลบออกทั้งหมดด้วย DROP POLICY หากลบนโยบายทั้งหมดในขณะที่ยังเปิดใช้ RLS อยู่ บทบาทที่ไม่ใช่เจ้าของจะไม่สามารถเข้าถึงแถวใดได้ หากต้องการนำ RLS ออกทั้งหมด ให้ปิดใช้ด้วย ALTER TABLE

-- Rename a policy
ALTER POLICY orders_owner_policy ON orders
  RENAME TO user_isolation_policy;

-- Update the USING expression
ALTER POLICY user_isolation_policy ON orders
  USING (owner = current_user AND amount >= 0);

-- Remove a policy
DROP POLICY admin_full_access ON orders;

-- Disable RLS entirely on the table
ALTER TABLE orders DISABLE ROW LEVEL SECURITY;

รูปแบบการใช้งานจริง: การแยกข้อมูลของผู้เช่าหลายราย

รูปแบบ RLS ที่ใช้กันทั่วไปในแอป SaaS แบบหลายผู้เช่าคือการเพิ่มคอลัมน์ รหัสผู้เช่า ในทุกตาราง และใช้ตัวแปรระดับเซสชัน (set_config) เพื่อส่งตัวระบุผู้เชื่อมต่อในขณะเชื่อมต่อ จากนั้นนโยบายจะเปรียบเทียบรหัสผู้เช่าของแต่ละแถวกับค่าดังกล่าว

-- Table with tenant isolation column
CREATE TABLE documents (
  id         SERIAL PRIMARY KEY,
  tenant_id  TEXT NOT NULL,
  title      TEXT
);

ALTER TABLE documents ENABLE ROW LEVEL SECURITY;

-- Policy reads the tenant from a session variable
CREATE POLICY tenant_isolation
  ON documents
  FOR ALL
  USING       (tenant_id = current_setting('app.tenant_id'))
  WITH CHECK  (tenant_id = current_setting('app.tenant_id'));

-- Application sets the variable before running queries
SELECT set_config('app.tenant_id', 'tenant_42', true);

-- Now only tenant_42 documents are visible
SELECT * FROM documents;

ตรวจสอบความเข้าใจ

ทดสอบความเข้าใจของคุณเกี่ยวกับนโยบายการรักษาความปลอดภัยระดับแถวใน PostgreSQL

ทบทวนบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า RLS ช่วยกรองแถวโดยอัตโนมัติตามนโยบายโดยตรงที่ระดับฐานข้อมูลได้อย่างไร:

  • เปิดใช้ RLS ในตารางด้วย ALTER TABLE ... ENABLE ROW LEVEL SECURITY
  • ใช้ CREATE POLICY ร่วมกับเงื่อนไข USING เพื่อกรองแถวที่อ่านได้ และเงื่อนไข WITH CHECK เพื่อตรวจสอบแถวที่เขียน
  • กำหนดขอบเขตของนโยบายให้กับคำสั่งเฉพาะ (SELECT, INSERT, UPDATE, DELETE, ALL) และบทบาทเฉพาะโดยใช้อนุประโยค TO
  • ผสมนโยบาย PERMISSIVE (ตรรกะ OR) และ RESTRICTIVE (ตรรกะ AND) เพื่อสร้างการควบคุม access แบบหลายชั้น
  • เจ้าของตารางและผู้ใช้ระดับสูงสุดจะข้าม RLS ได้โดยค่าเริ่มต้น ให้ใช้ FORCE ROW LEVEL SECURITY เพื่อบังคับใช้ RLS กับบุคคลเหล่านี้
  • รูปแบบหลายผู้เช่าที่ใช้ current_setting() เป็นการประยุกต์ใช้ RLS ในโลกจริงที่ทรงพลัง

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

เริ่มต้นได้ฟรี

เรียนรู้ SQL ด้วย AI tutor — ฟรี

เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป

คอร์ส
46
บทเรียน
183

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

บทเรียน “นโยบายความปลอดภัยระดับแถว” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “นโยบายความปลอดภัยระดับแถว” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส SQL Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส SQL Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “นโยบายความปลอดภัยระดับแถว”

กรองแถวตามผู้ใช้โดยอัตโนมัติ คุณปฏิบัติ SQL Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน SQL Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน SQL Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “นโยบายความปลอดภัยระดับแถว” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน SQL Academy นี้ได้ไหม

ได้ บทเรียน SQL Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. บทบาทและสิทธิ์
  2. นโยบายความปลอดภัยระดับแถว
  3. สิทธิ์ระดับคอลัมน์
  4. การตรวจสอบการเข้าถึง
← กลับไปที่ SQL Academy