Mở đầu: Tại sao cần Row Level Security?
Trong mọi ứng dụng web hay mobile, quản lý quyền truy cập dữ liệu luôn là một thách thức lớn. Nếu chỉ dừng lại ở việc phân quyền theo role, chúng ta vẫn có nguy cơ rò rỉ thông tin giữa các user. Row Level Security (RLS) ra đời để giải quyết vấn đề này: đảm bảo mỗi user chỉ nhìn thấy những dòng dữ liệu mà họ được phép xem, dựa trên các điều kiện cụ thể.
Hãy tưởng tượng một hệ thống CRM, nơi nhân viên kinh doanh chỉ được xem thông tin khách hàng trong khu vực của họ, hoặc một ứng dụng quản lý tài chính, nơi mỗi nhân viên chỉ truy cập được dữ liệu của bộ phận mình. RLS giúp triển khai những logic này một cách gọn gàng, bảo mật và dễ bảo trì.
Row Level Security là gì?
Row Level Security là một tính năng bảo mật cho phép kiểm soát truy cập ở cấp độ từng dòng (row) trong bảng dữ liệu. Thay vì chỉ chặn toàn bộ bảng hoặc theo role, RLS cho phép bạn định nghĩa các policy (chính sách) để lọc dữ liệu ngay tại database.
Ví dụ, với một bảng orders, bạn có thể tạo policy sao cho user A chỉ thấy các đơn hàng thuộc khu vực của họ, trong khi user B thấy đơn hàng của khu vực khác.
Ưu điểm của RLS
- Bảo mật tối ưu: Logic kiểm soát nằm ở database, không thể bị bypass từ application layer. - Dễ bảo trì: Chỉ cần thay đổi policy, không phải sửa code ứng dụng. - Hiệu năng tốt: Database tối ưu hóa việc lọc dữ liệu.
Xây dựng hệ thống quản lý user với RLS
Bước 1: Thiết kế database schema
Đầu tiên, chúng ta cần có các bảng cơ bản:
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
role VARCHAR(20) NOT NULL,
region_id INT
);
CREATE TABLE regions (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL
);
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INT REFERENCES users(id),
region_id INT REFERENCES regions(id),
amount DECIMAL(10, 2),
description TEXT
);
Mỗi user có thể thuộc một khu vực (region), và mỗi đơn hàng gắn với khu vực đó. Đây là nền tảng để xây dựng policy.
Bước 2: Bật Row Level Security
ALTER TABLE orders ENABLE ROW LEVEL SECURITY;
Khi bật RLS, mặc định tất cả các truy vấn vào bảng orders sẽ bị từ chối trừ khi có policy cho phép.
Bước 3: Tạo user và gán role
CREATE ROLE app_user;
GRANT USAGE ON SCHEMA public TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO app_user;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO app_user;
Mỗi user application sẽ đăng nhập với role app_user và được gán current_user tương ứng.
Quảng cáo
300x250 In-Content Advertisement
Bước 4: Định nghĩa policy
CREATE POLICY user_access_own_orders ON orders
FOR ALL
TO app_user
USING (user_id = (SELECT id FROM users WHERE username = current_user));
CREATE POLICY region_access_orders ON orders
FOR SELECT
TO app_user
USING (region_id = (SELECT region_id FROM users WHERE username = current_user));
Policy thứ nhất đảm bảo user chỉ thấy hoặc sửa được đơn hàng do chính họ tạo. Policy thứ hai cho phép user xem tất cả đơn hàng trong khu vực của họ (nhưng không sửa/xóa).
Bước 5: Kiểm thử
Đăng nhập với user john (thuộc region 1):
SET ROLE 'john';
SELECT * FROM orders;
Kết quả trả về chỉ bao gồm các đơn hàng của region 1, hoặc do john tạo ra.
Các lưu ý khi triển khai
1. Quản lý role trong application
Khi user đăng nhập vào ứng dụng, bạn cần set role tương ứng vào database session. Ví dụ với PostgreSQL và Node.js:
await client.query(SET ROLE '${username}');
2. Xử lý policy phức tạp
Nếu logic phân quyền phức tạp (ví dụ: manager xem được nhiều khu vực), bạn có thể thêm cột manager_region_ids hoặc bảng trung gian user_region_permissions và điều chỉnh policy tương ứng.
3. Audit và logging
Bật logging để theo dõi các truy vấn bị từ chối:
SET log_min_messages TO 'debug1';
Kết luận
Row Level Security là một công cụ mạnh mẽ giúp bảo vệ dữ liệu ở cấp độ chi tiết nhất. Thay vì dựa hoàn toàn vào application logic, bạn đặt security policy ngay tại database, giảm thiểu rủi ro bị bypass. Với thiết kế hợp lý và policy rõ ràng, hệ thống quản lý user của bạn sẽ vừa bảo mật, vừa dễ mở rộng.
Nếu bạn đang xây dựng một ứng dụng có dữ liệu nhạy cảm hoặc nhiều cấp độ truy cập, hãy cân nhắc áp dụng RLS từ sớm. Nó sẽ giúp bạn tiết kiệm thời gian bảo trì và tăng cường độ an toàn cho hệ thống.