Phân quyền
Hướng dẫn sử dụng chức năng xác thực phân quyền
Cơ chế#

Mỗi HTTP request sẽ bao gồm các thông tin#
- Headers : header của request (chứa mã token xác thực)
- URL :
protocol://domain:port/path[/id][?params query] - Method : Rest API tuân theo cấu trúc sử dụng HTTP method như sau
- GET có
id: Lấy thông tin của một bản ghi cụ thể - GET không
id: Lấy thông tin của tất cả các bản ghi thỏa mãnparams query - POST : Tạo mới dữ liệu
- PATCH có
id: cập nhật dữ liệu của bản ghi cụ thể - PATCH không
id: cập nhật dữ liệu của toàn bộ bản ghi thỏa mãnparams query - UPDATE có
id: thay mới dữ liệu của bản ghi cụ thể (không sử dụng) - UPDATE không
id: thay mới dữ liệu của toàn bộ bản ghi thỏa mãnparams query(không sử dụng) - DELETE có
id: xóa bản ghi cụ thể - DELETE không
id: xóa tất cả bản ghi thỏa mãnparams query
- GET có
- Data payload (json): Chứa dữ liệu cho các cuộc gọi
POSTPATCH
Thông tin của 1 cuộc gọi được xác định như sau#
Lưu ý các từ viết đậm này sẽ được sử dụng phía dưới
- HEADERS : là
headertrong cuộc gọi (được xử lý ở dạng Object) - PATH : là
pathtrong url tương ứng với 1 endpoint, service trong hệ thống. (Chuỗi) - ID : là
idtrong url cuộc gọi nếu có (xác định đối tượng dữ liệu cụ thể tác động dựa trên khóa chính_idtrong cơ sở dữ liệu). (Chuỗi) - QUERY : là
params querytrong url cuộc gọi, chỉ định tham số lọc của các truy vấn tìm kiếm chỉnh sửa (Object) - DATA : là
payloadChứa dữ liệu cho các cuộc gọiPOSTPATCH(Object)
Thông tin Roles của một tài khoản#
- Thông tin quyền hạn của một tài khoản được xác định trong cơ sở dữ liệu thông qua trường
roles. roleslà một mảng các chuỗi, mỗi phần tử là tên của 1 role.rolenào ở trước sẽ được ưu tiên duyệt trước. Quá trình duyệt sẽ dừng lại khi tìm được cấu hình quyền cho phép.
Quá trình xử lý#
- Các cuộc gọi API đi vào hệ thống sẽ được xác minh người dùng thông qua JWT trong trường
Authorization.- JWT được giải mã, xác định thông tin tài khoản thực hiện cuộc gọi
- Dữ liệu của người dùng sau khi được xác định được lưu trong Object USER
- Hệ thống lấy thông tin
rolescủa tài khoản thực hiện cuộc gọi. - Cuộc gọi được điều chỉnh thông qua module phân quyền. Duyệt lần lượt qua từng role của tài khoản.
- Thông tin cuộc gọi sau khi điều chỉnh được đẩy tới service.
Cấu trúc Dữ liệu phân quyền#
Mongoose Schema#
{ name: { type: String, trim: true, unique: true, required: true, index: true }, permissions: [{ url: { type: String }, method: Schema.Types.Mixed, forbidden: {type: Boolean, default: false}, limit: { whiteList: [{ _id: false, entity: { type: String }, idField: { type: String }, idValue: [Schema.Types.Mixed] }], blackList: [{ _id: false, entity: { type: String }, idField: { type: String }, idValue: [Schema.Types.Mixed] }], restrict: [{ _id: false, entity: { type: String }, idField: { type: String }, idValue: Schema.Types.Mixed, ownerField: { type: String }, }], skipPostRestrict: {type: Boolean, default: false}, custom: [{ _id: false, field: { type: String }, force: Schema.Types.Mixed, range: [Schema.Types.Mixed], default: Schema.Types.Mixed }], apiOptions: Schema.Types.Mixed } }]}name: Tên của rolepermissions: là mảng chứa danh sách thông tin phân quyền cho từng API endpointurl: là PATH (tên endpoint, service) xác định endpoint, service mà luật này tác động, "all" nếu tác động lên tất cả endpointmethod: xác định http method mà luật này tác động- find : tương ứng với GET không
id - get : tương ứng với GET có
id - create : tương ứng với POST : Tạo mới dữ liệu
- patch : tương ứng với PATCH có
idvà PATCH khôngid - update : tương ứng với UPDATE có
idvà UPDATE khôngid - remove : tương ứng với DELETE có
idvà DELETE khôngid
- find : tương ứng với GET không
forbidden: boolean , true nếu cấm sử dụnglimitwhiteList: Mảng danh sách cho phép sử dụng api (trả về lỗi nếu không nằm trong danh sách) (Xử lý trước blackList)entity: tên object truy xuất thông tin của truy vấn (chuỗi)idField: tên trường trong objectentityidValue: mảng chứa danh sách các giá trị được phép của trường dữ liệu trên
blackList: mảng danh sách không cho phép sử dụng api (trả về lỗi nếu nằm trong danh sách)entity: tên object truy xuất thông tin của truy vấn (chuỗi)idField: tên trường trong objectentityidValue: mảng chứa danh sách các giá trị không được phép của trường dữ liệu trên
restrict: mảng các luật sẽ tác động điều chỉnh lên QUERYentity: tên object truy xuất thông tin của truy vấn (chuỗi)idField: tên trường trong objectentityidValue: Nếu không sử dụngentity.idField. Có thể sử dụng giá trị cố định bằng trường nàyownerField: chuỗi tên trường cần điều chỉnh trong QUERY. Nếu muốn tác động kiểm tra ID, trường này sẽ để giá trị là "__id__"- Nếu
entity.idFieldkhông tồn tại thì bỏ qua giới hạn này
skipPostRestrict: boolean , true nếu bỏ qua quá trình giới hạn phân quyền dựa trên bản ghi sở hữurelations. Thường sử dụng đối với các role tài khoản quản trịcustom: mảng các luật tác động điều chỉnh lên DATA (Chỉ các động lên method POST và PATCH, UPDATE)field: Chuỗi tên trường cần điều chỉnh, kiểm tra trong DATAforce: Thông tin điều chỉnh ép buộc. Có thể là 1 trong 2 kiểu- Giá trị cụ thể
- Object chứa thông tin
clear: Xóa trường nàyentity: tên object truy xuất thông tin của truy vấn (chuỗi)idField: tên trường trong objectentity- Nếu
entity.idFieldkhông tồn tại thì sẽ trả về lỗi truy vấn không được phép
- Nếu
range: Nếu không sử dụngforce. Mảng này chứa thông tin các giá trị được phép của giá trị của trườngfield- Mỗi phần tử có thể là :
- Giá trị cụ thể
- Object chứa thông tin
entity: tên object truy xuất thông tin của truy vấn (chuỗi)idField: tên trường trong objectentity
- Nếu giá trị của trường dữ liệu không nằm trong giới hạn này thì hệ thống sẽ coi như luật này không có tác động và bỏ qua.
- Mỗi phần tử có thể là :
default: Sau khi xử lý các trường trên, nếu trường dữ liệu không tồn tại trong truy vấn. Giá trị mặc định được áp dụng. Có 2 kiểu giá trị:- Gía trị cụ thể
- Object chứa thông tin:
entity: tên object truy xuất thông tin của truy vấn (chuỗi)idField: tên trường trong objectentity
apiOptions: Object dữ liệu cấu hình đặc thù dành riêng cho API endpoint nếu có
Giá trị của trường thông tin entity#
entity là tên trường của Obejct feathersjs params
Các trường bạn thường sử dụng là:
- "user" : Thông tin của tài khoản thực hiện truy vấn
- "headers" : Header của truy vấn
- "payload" : Thông tin trong JWT mà cuộc gọi sử dụng
Ví dụ#
Api endpoint users#
- Không cho phép điều chỉnh trường
rolesvàmanufacturerIdtrong apiusers
{ "forbidden" : false, "method" : "all", "url" : "users", "limit" : { "skipPostRestrict" : false, "custom" : [ { "range" : [], "force" : { "clear" : true }, "field" : "roles" }, { "range" : [], "force" : { "clear" : true }, "field" : "manufacturerId" } ], "restrict" : [], "whiteList" : [], "blackList" : [] }}- Chỉ cho phép lấy và tác động lên thông tin của bản thân trong api
users
{ "forbidden" : false, "method" : "all", "url" : "users", "limit" : { "skipPostRestrict" : false, "custom" : [], "restrict" : [ { "entity" : "user", "idField" : "_id", "ownerField" : "_id" }, { "entity" : "user", "idField" : "_id", "ownerField" : "__id__" } ], "whiteList" : [], "blackList" : [] }}- Kết hợp cả 2 luật trên
{ "forbidden" : false, "method" : "all", "url" : "users", "limit" : { "skipPostRestrict" : false, "custom" : [ { "range" : [], "force" : { "clear" : true }, "field" : "roles" }, { "range" : [], "force" : { "clear" : true }, "field" : "manufacturerId" } ], "restrict" : [ { "entity" : "user", "idField" : "_id", "ownerField" : "_id" }, { "entity" : "user", "idField" : "_id", "ownerField" : "__id__" } ], "whiteList" : [], "blackList" : [] }}- Chỉ cho phép tác động lên các bản ghi user có trường
manufacturerIdbằng vớimanufacturerIdcủa tài khoản thực hiện truy vấn. (nếu tài khoản thực hiện truy vấn không cómanufacturerIdthì bỏ qua giới hạn này). Đồng thời giới hạn thao tác chỉnh sửa trườngmanufacturerIdbuộc phải bằngmanufacturerIdcủa tài khoản truy vấn, trườngrolesbuộc phải nằm trong danh sách giá trị "user","adminPartner","tester","department","cskh","agent"
{ "forbidden" : false, "method" : "all", "url" : "users", "limit" : { "skipPostRestrict" : false, "custom" : [ { "range" : [], "force" : { "entity" : "user", "idField" : "manufacturerId" }, "field" : "manufacturerId" }, { "range" : [ "user", "adminPartner", "tester", "department", "cskh", "agent" ], "field" : "roles" } ], "restrict" : [ { "entity" : "user", "idField" : "manufacturerId", "ownerField" : "manufacturerId" } ], "whiteList" : [], "blackList" : [] }}Giao diện#
Giao diện quản lý phân quyền#

Giao diện điều chỉnh phân quyền cho 1 API endpoint#
