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
POST
PATCH
#
Thông tin của 1 cuộc gọi được xác định như sauLưu ý các từ viết đậm này sẽ được sử dụng phía dưới
- HEADERS : là
header
trong cuộc gọi (được xử lý ở dạng Object) - PATH : là
path
trong url tương ứng với 1 endpoint, service trong hệ thống. (Chuỗi) - ID : là
id
trong 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_id
trong cơ sở dữ liệu). (Chuỗi) - QUERY : là
params query
trong 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à
payload
Chứa dữ liệu cho các cuộc gọiPOST
PATCH
(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
. roles
là một mảng các chuỗi, mỗi phần tử là tên của 1 role.role
nà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
roles
củ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ó
id
và PATCH khôngid
- update : tương ứng với UPDATE có
id
và UPDATE khôngid
- remove : tương ứng với DELETE có
id
và DELETE khôngid
- find : tương ứng với GET không
forbidden
: boolean , true nếu cấm sử dụnglimit
whiteList
: 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 objectentity
idValue
: 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 objectentity
idValue
: 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 objectentity
idValue
: 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
.idField
khô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
.idField
khô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ó
entity
#
Giá trị của trường thông tin 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ụusers
#
Api endpoint - Không cho phép điều chỉnh trường
roles
vàmanufacturerId
trong 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
manufacturerId
bằng vớimanufacturerId
củ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ómanufacturerId
thì bỏ qua giới hạn này). Đồng thời giới hạn thao tác chỉnh sửa trườngmanufacturerId
buộc phải bằngmanufacturerId
của tài khoản truy vấn, trườngroles
buộ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" : [] }}