Lớp phòng thủ cuối cùng biết dữ liệu thuộc về ai
Bốn bài trước đều dựa vào một điều: có người nhớ viết mệnh đề đúng. Mệnh đề WHERE cần người viết, Expression dùng chung cần người gọi, DTO cần người khai. Row Level Security là lớp duy nhất không cần ai nhớ gì — nó chạy bên trong cơ sở dữ liệu, sau mọi câu truy vấn, kể cả câu truy vấn của một psql mở tay lúc 3 giờ sáng.
Cách hoạt động, ngắn gọn: bạn khai một policy trên bảng, và Postgres tự thêm điều kiện của policy đó vào mọi truy vấn chạm tới bảng. Không phải "kiểm tra rồi từ chối" mà là hàng không thoả điều kiện thì không tồn tại đối với câu truy vấn đó. SELECT count(*) trả về số nhỏ hơn; UPDATE không update gì; DELETE không xoá gì.
Điểm khiến nó khác về bản chất so với bốn bài trước:
| Lớp | Bảo vệ được gì | Không bảo vệ được gì |
|---|---|---|
Mệnh đề WHERE | Endpoint có người viết mệnh đề | Endpoint thứ hai, job nền, migration script |
| Mặc định từ chối ở pipeline | Request đi qua HTTP | Mọi thứ không đi qua HTTP |
Expression dùng chung | Chỗ có người gọi nó | Chỗ quên gọi |
| RLS | Mọi câu truy vấn tới bảng đó, từ mọi nguồn | Xem bước cuối — có ba đường vượt qua |
Và đây là chỗ phải nói rõ, vì nó là cái bẫy lớn nhất của bài này: RLS là lớp thứ hai, không phải lớp thứ nhất. Bật RLS rồi bỏ mệnh đề WHERE trong code là một sai lầm: bạn mất khả năng đọc quy tắc từ code ứng dụng, mất kiểm soát về hiệu năng (policy tham gia vào kế hoạch truy vấn), và bạn đặt toàn bộ phân quyền vào một cơ chế mà một lần cấu hình sai kết nối là tắt hoàn toàn.
Bình luận
Bình luận cần tài khoản đã hoàn thành ít nhất một bài học. Điều kiện đó là thứ giữ cho luồng thảo luận này còn đáng đọc: mỗi ý kiến gắn với một người có thể bị hỏi lại, và reputation tích luỹ theo thời gian.
Bạn vẫn đọc được toàn bộ bình luận dưới đây mà không cần tài khoản. Đăng nhập xong bạn sẽ quay lại đúng chỗ này, không phải đầu trang.
Đang tải bình luận…