CodeGym /課程 /SQL SELF /行級存取控制:Row-Level Security (RLS)

行級存取控制:Row-Level Security (RLS)

SQL SELF
等級 47, 課堂 3
開放

如果角色和資料表層級的權限像是「大門口的保全」,那 Row-Level Security 就像是每個房間門口都站一個保全,會檢查每個用戶能不能進這間房。

RLS 幫你做到讓用戶只能操作他被允許的那些資料表行。舉例來說:

  • 在網路商店,經理只能看到自己的訂單。
  • 在 CRM 平台,員工只能看到自己團隊的客戶。
  • 在銀行系統,客戶只能存取自己的帳戶。

RLS 怎麼運作

RLS 的核心概念是存取政策。政策會定義哪些資料表行對某個角色或用戶可見,以及哪些可以被改動(INSERT、UPDATE、DELETE)。

預設情況下,RLS 是關閉的,你要自己手動開啟。

啟用資料表的 RLS

我們來建立一個 orders 資料表,裡面存網路商店的訂單:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    user_id INT NOT NULL,
    product_name TEXT NOT NULL,
    price NUMERIC NOT NULL
);

加一些測試資料:

INSERT INTO orders (user_id, product_name, price)
VALUES
    (1, '智慧型手機', 500),
    (2, '筆記型電腦', 1000),
    (1, '耳機', 100),
    (3, '鍵盤', 50);

現在來啟用這個資料表的 RLS:

ALTER TABLE orders ENABLE ROW LEVEL SECURITY;

我們做了什麼?我們啟動了 RLS 機制,但還沒設定任何政策。只要還沒建立政策,RLS 其實不會影響資料表存取。

建立存取政策

要加存取規則,用這個指令:

CREATE POLICY 政策名稱
ON 資料表
[FOR { SELECT | INSERT | UPDATE | DELETE }]
TO 角色
USING (存取條件)
WITH CHECK (檢查條件);
  • FOR:定義這個政策適用哪些操作(SELECT、INSERT、UPDATE、DELETE)。如果省略,政策會套用到所有操作。
  • TO:指定哪些角色會套用這個政策。如果沒寫,所有角色都會套用。
  • USING:設定什麼條件下,行會對用戶可見。
  • WITH CHECK:定義 INSERT 和 UPDATE 操作時要檢查的條件。

範例:只能看到自己的訂單

我們來做一個政策,讓用戶只能看到自己的訂單。假設目前用戶的 id 跟資料表裡的 user_id 一樣:

CREATE POLICY user_can_view_own_orders
ON orders
FOR SELECT
USING (user_id = current_user::INT);

這裡發生什麼事?

  • 政策名稱叫 user_can_view_own_orders。
  • 它只套用在 SELECT 操作。
  • 只有 user_id 跟目前用戶 id(current_user)一樣的行才看得到。

所以,如果你是 user_id = 1 的用戶登入,你只會看到自己的訂單。

檢查 RLS 運作

我們來建立兩個用戶:user1 和 user2。

CREATE ROLE user1 LOGIN PASSWORD 'password1';
CREATE ROLE user2 LOGIN PASSWORD 'password2';

給這些角色資料表的存取權:

GRANT SELECT ON orders TO user1, user2;

現在切換到 user1,試著查詢:

SELECT * FROM orders;

結果:你只會看到 user_id = 1 的行。

INSERT 的政策

假設我們想讓用戶只能新增自己的訂單(也就是 user_id 必須跟目前用戶 id 一樣)。

來建立一個 INSERT 政策:

CREATE POLICY user_can_insert_own_orders
ON orders
FOR INSERT
WITH CHECK (user_id = current_user::INT);

現在,如果 user1 想新增一筆 user_id 不是 1 的訂單,查詢就會報錯。

UPDATE 和 DELETE 的政策

同樣方式可以建立修改和刪除的政策。例如:

只能更新自己的資料:

CREATE POLICY user_can_update_own_orders
ON orders
FOR UPDATE
USING (user_id = current_user::INT)
WITH CHECK (user_id = current_user::INT);

只能刪除自己的資料:

CREATE POLICY user_can_delete_own_orders
ON orders
FOR DELETE
USING (user_id = current_user::INT);

多個政策一起用

你可以為同一個資料表建立多個政策。它們會同時生效。如果同一個角色有多條規則,PostgreSQL 會全部檢查(邏輯 AND)。

檢查和 debug RLS

要查資料表有哪些政策,用這個指令:

\di+ 資料表名稱

如果你想暫時關掉 RLS(比如管理員要用),可以執行:

ALTER TABLE orders DISABLE ROW LEVEL SECURITY;

管理員角色 SUPERUSER 預設不受 RLS 限制,所以可以看到所有資料。

設定 RLS 常見錯誤

常見錯誤有:

  • 忘記用 ALTER TABLE ... ENABLE ROW LEVEL SECURITY 開啟 RLS。
  • 沒為所有操作(SELECT、INSERT、UPDATE、DELETE)設政策。
  • USING 和 WITH CHECK 條件寫錯。比如沒檢查 user_id,就可能讓所有人都能看到所有行。

Row-Level Security 是 PostgreSQL 裡最強大的安全工具之一。它可以精確到每一行來控管存取權,還能自動化權限管理,對於需要高資料保護的複雜應用超級重要!

2
任務
SQL SELF, 等級 47, 課堂 3
上鎖
複合政策:讀取與編輯權限
複合政策:讀取與編輯權限
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION