Bỏ qua, đến nội dung

Security model

Bảo mật trong Digiforce gồm hai engine: AuthManager (xác thực - ai đang gọi) và ACL Engine (phân quyền - được làm gì). Cả hai nằm bên trong data source pipeline, không phải middleware Koa cấp app. Trang này mô tả ở mức kiến trúc; deep dive code-level: Core: ACLCore: Auth.


1) Vị trí trong pipeline

Thứ tự trong data source pipeline (Toposort):

  1. validate-filter-params
  2. auth - xác thực
  3. ResourceManager - parse resource + action
  4. acl - phân quyền (sau auth)
  5. parseVariables, dataTemplate
  6. Pre-action → handler

2) AuthManager - xác thực

Kiến trúc

  • AuthManager giữ JwtService (ký/verify JWT), map auth types, storer (đọc authenticator config từ DB).
  • Plugin đăng ký kiểu xác thực: authManager.registerTypes('password', { auth: PasswordAuth, title: 'Password' }).
  • Storer đọc collection authenticators để lấy config cho từng kiểu auth.

Auth middleware flow

skipCheck() trả true khi:

  • ctx.skipAuthCheck === true, hoặc
  • Không có bearer token ctx.app.options.acl === false, hoặc
  • Action được ACL coi là public (acl.allowManager.isPublic(resource, action, ctx)).

JWT lifecycle


3) ACL Engine - phân quyền

Kiến trúc

Thành phầnVai trò
rolesMap role → ACLRole; define bằng acl.define({ role, strategy?, actions?, snippets? }).
AllowManagerNgoại lệ: cho phép resource/action theo điều kiện (public, loggedIn, hàm tùy chỉnh).
SnippetManagerNhóm quyền theo glob pattern (ui.*, pm.*); gán cho role.
FixedParamsManagerMerge filter/params cố định vào kết quả can() (ví dụ ownedBy: currentUser).
availableActionsAction khả dụng cho collection (export, import, …) - plugin đăng ký.
availableStrategyStrategy mặc định cho role (view own, edit own, …).

Luồng can() - quyết định phân quyền

ACL middleware flow

Snippet - nhóm quyền

Snippet dùng glob pattern (minimatch) trên path resource:action:

Snippet namePatternÝ nghĩa
ui.*ui.*Toàn bộ UI config actions
pm.*pm.*Plugin manager actions
!pm.remove!pm:removePhủ định: cấm xóa plugin

Role gán snippet; khi can() kiểm tra, SnippetManager match pattern.

Fixed params - filter ngầm

FixedParamsManager gộp filter vào mỗi request đã được allow. Ví dụ: role member chỉ xem record do mình tạo → fixed param filter: { createdById: '{{ ctx.state.currentUser.id }}' }.


4) Tích hợp Auth ↔ ACL

  • Auth resolve currentUsercurrentRole (mặc định anonymous nếu không đăng nhập).
  • ACL nhận currentRole → kiểm tra quyền.
  • Action public (đăng ký qua acl.allow) → skipCheck() = true ở Auth → ACL cũng allow.

5) Plugin plugin-acl vs core @digiforce-nc/acl

LayerPackageVai trò
Core library@digiforce-nc/aclEngine in-memory: ACL, ACLRole, AllowManager, can().
Plugin runtimeplugin-aclĐồng bộ DB → ACL: đọc roles/permissions từ DB, gọi acl.define().

Core ACL là stateless engine - không biết database. Plugin ACL đọc cấu hình từ collection roles, rolesResources, rolesResourcesActions rồi feed vào engine.


6) Checklist bảo mật khi mở rộng

KhiLàm gì
Thêm resource/action mớiĐăng ký acl.allow(...) hoặc setAvailableAction để gán quyền.
Endpoint cần public (không auth)acl.allow(resource, actions, 'public') - tránh dùng cho write actions.
Giới hạn "chỉ xem record của mình"Fixed params: filter.createdById = currentUser.id.
Plugin cần snippet mớiacl.registerSnippet({ name, actions }) với glob pattern phù hợp.
Action ghi dữ liệuLuôn qua ACL; dùng transaction; validate trước Repository.

Đọc tiếp