如果角色和資料表層級的權限像是「大門口的保全」,那 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 裡最強大的安全工具之一。它可以精確到每一行來控管存取權,還能自動化權限管理,對於需要高資料保護的複雜應用超級重要!
GO TO FULL VERSION