Hướng dẫn

Cách thêm kiểm soát truy cập theo vai trò (RBAC) vào ứng dụng

Để thêm kiểm soát truy cập theo vai trò, hãy gán cho mỗi người dùng một hoặc nhiều vai trò (ví dụ quản trị viên, biên tập viên, người xem), xác định mỗi vai trò được thực hiện những hành động nào, và kiểm tra các quyền đó trên server cho mọi yêu cầu — không chỉ bằng cách ẩn nút. Đồng thời kiểm tra xem bản ghi đang được truy cập có thuộc về tài khoản hoặc nhóm của người dùng hay không. Hãy bắt đầu với vài vai trò cố định trong cơ sở dữ liệu, và kiểm thử bằng cách thử truy cập trực tiếp vào dữ liệu của người dùng khác.

Xác thực và phân quyền

Hai từ hay bị nhầm lẫn:

  • Xác thực (Authentication) là bạn là ai? — đăng nhập. Xem cách thêm đăng nhập vào ứng dụng.
  • Phân quyền (Authorisation) là bạn được phép làm gì? — những trang, bản ghi và hành động nào người dùng đã đăng nhập có thể truy cập.

RBAC là cách phổ biến nhất để phân quyền. Điều này quan trọng: tính đến tháng 9 năm 2026, Broken Access Control đứng số 1 trong OWASP Top 10:2025, danh sách rủi ro bảo mật ứng dụng web nghiêm trọng nhất được sử dụng rộng rãi. Các lỗi điển hình là người dùng đọc được bản ghi của người khác bằng cách thay đổi ID trên URL, hoặc người dùng thông thường gọi các route API chỉ dành cho quản trị viên.

Chọn mô hình

Mô hìnhCách hoạt độngPhù hợp vớiĐánh đổi
Một cột vai trò đơnusers.role = admin / memberỨng dụng nhỏ với hai hoặc ba vai tròTrở nên rối khi mọi người cần các vai trò khác nhau ở các nơi khác nhau
Vai trò + quyền hạnVai trò ánh xạ đến các quyền có tên (invoices.approve); code kiểm tra quyềnỨng dụng có quy tắc sẽ phát triển thêmNhiều bảng hơn; phải duy trì danh sách quyền
Vai trò theo nhóm (multi-tenant)Bảng thành viên: người dùng + tổ chức + vai tròSaaS mà mọi người thuộc về các nhóm hoặc workspaceMọi truy vấn phải được giới hạn trong tổ chức
Dựa trên thuộc tính hoặc quan hệQuy tắc dựa trên thuộc tính bản ghi ("tác giả có thể sửa bài của chính mình") hoặc quan hệ (được chia sẻ với)Tài liệu, chia sẻ, quy trình phức tạpKhó suy luận hơn; cân nhắc một thư viện hoặc dịch vụ chuyên dụng
Vai trò từ nhà cung cấp xác thựcNhà cung cấp đăng nhập của bạn lưu vai trò hoặc tư cách thành viên tổ chứcỨng dụng đã dùng nhà cung cấp xác thực được lưu trữGắn chặt với nhà cung cấp đó; vẫn phải thực thi trên server của bạn

Trong thực tế, đa số ứng dụng kết hợp hai thứ: vai trò cho loại hành động người ta có thể thực hiện, và quyền sở hữu cho những bản ghi họ có thể thực hiện hành động đó. "Biên tập viên có thể sửa bài viết" là một quy tắc vai trò; "…bài viết trong workspace của họ" là một quy tắc quyền sở hữu. Bạn cần cả hai.

Hãy bắt đầu đơn giản hơn bạn nghĩ. Quản trị viên, thành viên và người xem đã bao quát một số lượng ứng dụng đáng ngạc nhiên. Tách một vai trò sau này dễ hơn nhiều so với việc gỡ rối mười vai trò mà không ai hiểu.

Thiết kế vai trò trước khi viết code

Hãy viết bảng quyền hạn bằng ngôn ngữ thông thường trước. Nó vừa là đặc tả cho AI, vừa là kế hoạch kiểm thử của bạn:

Hành độngChủ sở hữuQuản trị viênThành viênNgười xem
Xem các dự án trong nhóm✓✓✓✓
Tạo và sửa dự án✓✓✓
Xóa dự án✓✓
Mời và xóa người✓✓
Đổi vai trò✓
Thanh toán✓

Cũng hãy quyết định các trường hợp biên: chủ sở hữu cuối cùng có được rời đi không? Quản trị viên có được xóa chủ sở hữu không? Người dùng bị xóa sẽ thấy gì?

Từng bước

1. Có đăng nhập hoạt động trước

RBAC nằm trên lớp xác thực. Server phải biết chắc chắn ai đang thực hiện mỗi yêu cầu, từ session hoặc token đã xác minh — không bao giờ từ một user ID do trình duyệt gửi trong nội dung yêu cầu.

2. Lưu vai trò trong cơ sở dữ liệu

Với ứng dụng chỉ có một nhóm, một cột role trên bảng người dùng là đủ. Với nhiều nhóm, hãy dùng bảng thành viên:

create table memberships (
  user_id uuid references users(id),
  organization_id uuid references organizations(id),
  role text not null check (role in ('owner','admin','member','viewer')),
  primary key (user_id, organization_id)
);

Không bao giờ để người dùng tự đặt vai trò của mình qua một lần cập nhật hồ sơ thông thường. Việc thay đổi vai trò phải đi qua một endpoint riêng, có kiểm tra quyền.

3. Kiểm tra quyền trên server, ở một nơi duy nhất

Viết một hàm trợ giúp — kiểu như can(user, 'projects.delete', project) — và gọi nó trong mọi route API, server action và tác vụ nền đọc hoặc thay đổi dữ liệu. Một hàm trung tâm dễ xem xét và kiểm thử hơn các kiểm tra rải rác khắp code. Mặc định là từ chối: nếu không có quy tắc nào cho phép một hành động, hành động đó bị từ chối.

4. Giới hạn mọi truy vấn

Mọi truy vấn cho dữ liệu nhóm phải bao gồm nhóm: where organization_id = :currentOrg, không chỉ where id = :id. Đây là điều ngăn người ta đổi /projects/123 thành /projects/124 và xem dự án của công ty khác. Với bản ghi thuộc nhóm khác, hãy trả về "không tìm thấy" thay vì "bị cấm", để không tiết lộ rằng chúng tồn tại.

5. Thêm bảo vệ ở mức cơ sở dữ liệu ở những nơi quan trọng

Row-level security của Postgres (RLS) cho phép cơ sở dữ liệu thực thi việc mỗi người dùng được thấy những dòng nào. Nó thiết yếu nếu trình duyệt nói chuyện trực tiếp với cơ sở dữ liệu (như với một số backend được lưu trữ), và là lớp thứ hai hữu ích cho các bảng nhạy cảm trong trường hợp còn lại.

6. Phản ánh vai trò trên giao diện

Bây giờ hãy ẩn hoặc vô hiệu hóa những gì người dùng không được làm, để ứng dụng không gây nhầm lẫn. Điều này chỉ nhằm mục đích tiện dụng; việc bảo vệ thực sự do các kiểm tra trên server đảm nhiệm.

7. Ghi nhật ký các hành động nhạy cảm

Ghi lại ai đã thay đổi vai trò, xóa dữ liệu hoặc xuất bản ghi, và vào lúc nào. Nhật ký kiểm toán giúp trả lời các câu hỏi hỗ trợ và xử lý sự cố.

8. Kiểm thử như một kẻ tấn công

Đăng nhập bằng từng vai trò và thử mọi hành động trong bảng quyền hạn. Sau đó thử những việc không được phép xảy ra: gọi route API quản trị khi là người xem, đổi ID trong URL và yêu cầu, xóa chính mình khi là chủ sở hữu cuối cùng. Đáng viết các kiểm thử tự động cho bảng quyền hạn khi các quy tắc đã ổn định.

Các prompt hiệu quả

Thêm kiểm soát truy cập theo vai trò. Vai trò theo từng tổ chức: owner, admin, member, viewer, được lưu trong bảng memberships. Quyền hạn nằm trong bảng này: [dán bảng của bạn]. Tạo một hàm can(user, action, resource) duy nhất phía server, mặc định từ chối, và dùng nó trong mọi route API. Giới hạn mọi truy vấn theo organization_id. Ẩn các hành động mà người dùng không thể thực hiện trong giao diện, nhưng không bao giờ dựa vào điều đó để bảo mật.

Rà soát mọi route API và hàm server trong ứng dụng này. Với mỗi cái, liệt kê dữ liệu nó đọc hoặc thay đổi, nó có kiểm tra người dùng đã đăng nhập không, có kiểm tra vai trò không, và có giới hạn truy vấn theo tổ chức không. Sửa những chỗ thiếu kiểm tra, và cho tôi xem danh sách.

Thêm trang /admin chỉ dành cho quản trị viên, nơi chủ sở hữu có thể đổi vai trò của thành viên. Ngăn việc xóa hoặc hạ cấp chủ sở hữu cuối cùng, ghi nhật ký mọi thay đổi vai trò kèm người thực hiện và thời điểm, và đảm bảo endpoint đổi vai trò từ chối bất kỳ ai không phải chủ sở hữu.

Những lỗi thường gặp

  • Chỉ kiểm tra vai trò ở phía frontend. API vẫn mở cho bất kỳ ai gọi nó.
  • Tin tưởng ID từ client — một userId hoặc role trong nội dung yêu cầu thay vì lấy từ session.
  • Truy vấn không giới hạn chỉ lấy theo ID bản ghi.
  • Vai trò được kiểm tra ở các trang nhưng không ở route API, xuất dữ liệu, tải tệp hoặc webhook.
  • Quản trị viên theo địa chỉ email được viết cứng trong code (if email === 'me@...'), dễ quên và khó thay đổi.
  • Quá nhiều vai trò quá sớm, mà sáu tháng sau không ai giải thích được.
  • Session cũ: một người bị hạ cấp vẫn giữ quyền quản trị cho đến khi đăng xuất. Hãy kiểm tra vai trò từ cơ sở dữ liệu, hoặc làm mới chúng, khi thực hiện các hành động nhạy cảm.

Danh sách kiểm tra RBAC

  • Bảng quyền hạn được viết bằng ngôn ngữ thông thường, các trường hợp biên đã được quyết định
  • Server biết người dùng từ session, không bao giờ từ dữ liệu yêu cầu
  • Vai trò được lưu trong cơ sở dữ liệu; người dùng không thể tự thay đổi
  • Một kiểm tra quyền trung tâm, mặc định từ chối, được dùng trong mọi route
  • Mọi truy vấn được giới hạn theo tổ chức hoặc quyền sở hữu của người dùng
  • Có row-level security ở nơi trình duyệt có thể truy cập cơ sở dữ liệu
  • Giao diện ẩn những gì người dùng không thể làm (chỉ để tiện dụng)
  • Các hành động nhạy cảm được ghi nhật ký
  • Mỗi vai trò đã được kiểm thử, kể cả gọi API trực tiếp và đổi ID

Kiểm soát truy cập chỉ là một mục trong danh sách dài hơn; danh sách kiểm tra bảo mật cho ứng dụng xây bằng AI đề cập phần còn lại. Nếu bạn đang xây công cụ cho nhân viên nội bộ, cách xây công cụ nội bộ cho thấy vai trò phù hợp ở đâu.

RBAC trên Mythex

Mythex không cung cấp hệ thống đăng nhập hoặc vai trò tích hợp sẵn cho người dùng ứng dụng của bạn. Bạn chọn một thư viện hoặc nhà cung cấp xác thực và mô tả các vai trò, rồi agent sẽ kết nối chúng vào code và cơ sở dữ liệu Postgres của dự án (thêm đăng nhập vào ứng dụng). Các vai trò workspace của chính Mythex, như Owner và Member, kiểm soát ai có thể chỉnh sửa dự án Mythex của bạn, chứ không phải ai được dùng ứng dụng bạn đã publish. Hãy dùng chế độ Plan để thống nhất bảng quyền hạn trước khi xây, rồi dùng prompt rà soát ở trên và kiểm thử mọi vai trò trong Preview trước khi publish. Các prompt bảo mật trong tài liệu là phần theo dõi hữu ích.

Câu hỏi thường gặp

Kiểm soát truy cập theo vai trò là gì?

Kiểm soát truy cập theo vai trò (RBAC) quyết định mỗi người dùng được làm gì dựa trên các vai trò họ nắm giữ, chẳng hạn quản trị viên, biên tập viên hoặc người xem. Quyền hạn được gắn vào vai trò thay vì từng cá nhân, nên thay đổi những gì ai đó được làm chỉ là đổi vai trò của họ.

Xác thực và phân quyền khác nhau thế nào?

Xác thực kiểm tra người dùng là ai, thường bằng đăng nhập. Phân quyền quyết định người đã đăng nhập đó được phép xem và làm gì. RBAC là một cách để thực hiện phân quyền.

Chỉ ẩn nút trên giao diện có đủ để hạn chế truy cập không?

Không. Bất kỳ ai cũng có thể gọi trực tiếp API của bạn, nên ẩn một nút chỉ thay đổi những gì người ta nhìn thấy. Mọi yêu cầu đọc hoặc thay đổi dữ liệu phải được kiểm tra trên server dựa trên vai trò của người dùng và quyền sở hữu bản ghi.

Có nên dùng row-level security của Postgres không?

Row-level security cho phép chính cơ sở dữ liệu thực thi việc mỗi người dùng được đọc hoặc ghi những dòng nào, đây là một lớp an toàn mạnh, đặc biệt khi frontend nói chuyện trực tiếp với cơ sở dữ liệu. Nó làm tăng độ phức tạp, nên nhiều ứng dụng thực thi quyền hạn trong code server và dùng row-level security như một lớp bổ sung cho các bảng nhạy cảm.

Mythex · Pricing · Xây dựng mọi thứ với AI · Mẫu website và ứng dụng · So sánh Mythex · Thuật ngữ xây dựng ứng dụng bằng AI · Công cụ miễn phí để xây dựng ứng dụng bằng AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو 简体中文 繁體中文(香港) 繁體中文(台灣)