Многие реализации RBAC (управление доступом на основе ролей) различаются, но основные принципы широко распространены, поскольку они имитируют назначение реальных ролей (должностей). —Онур Йылдырым.
Управление доступом на основе ролей (RBAC) — это метод изменения доступа и привилегий на основе ролей отдельных пользователей или групп пользователей в организации.
RBAC позволяет членам организации иметь доступ только к тем ресурсам, которые им необходимы для выполнения их работы, и ограничивает или запрещает неограниченные привилегии для ресурсов, которые им не принадлежат.
RBAC против ABAC
Управление доступом на основе ролей и управление доступом на основе атрибутов (ABAC) являются типами методов управления доступом, но их подходы различаются. Вариант использования, для которого требуется система RBAC, будет состоять в том, что мы намерены предоставлять привилегии приложению в зависимости от ролей пользователей.
В то время как ABAC предоставляет доступ на основе комбинации атрибутов, то есть атрибутов пользователя, атрибутов ресурсов, атрибутов, связанных с системой или приложением, к которым осуществляется доступ, атрибутов среды и т. д. Например, атрибуты пользователя могут включать биоданные, уникальные идентификаторы, роль, уровень допуска и т. д.
Предыстория
В недавнем проекте перед моей командой была поставлена задача реализовать пользовательскую структуру управления доступом на основе ролей для MongoDB (NoSQL DB) с использованием схемы ORM mongoose. В этой структуре управления доступом мы рассмотрим 3 объекта:
Контекст реализации
- У пользователя есть роль
- Приложение определило Ресурсы и,
- Роль имеет привилегии и разрешения на ресурсы
давайте напишем схемы мангустов для наших коллекций 😄
Схема
resources.models.js
/* RBAC - role-based access control
first create roles; role =[ "user", "guest", "organization", "superadmin" "globalsuperadmin"]
next, create resouuce, add their roles_id and permmissions
finally create users and indcate thier roles
*/
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient;
const resources = new Schema({
name: { type: String, required: true },
slug: { type: String, required: true },
resources_roles: [{
roles_id: { type: Schema.Types.ObjectId, ref : 'Roles' },
roles_name: { type: String },
create: { type: Boolean },
delete: { type: Boolean },
update: { type: Boolean },
read: { type: Boolean },
}]
}, {
timestamps: true
});
return mongooseClient.model('resources', resources);
roles.models.js
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient;
module.exports = function (app) {
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient;
const roles = new Schema({
name: { type: String, required: true },
slug: { type: String, required: true },
}, {
timestamps: true
});
return mongooseClient.model('roles', roles);
};
users.models.js
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient;
module.exports = function (app) {
const mongooseClient = app.get('mongooseClient');
const { Schema } = mongooseClient
const users = new mongooseClient.Schema({
email: {type: String, unique: true, lowercase: true},
password: { type: String },
first_name: { type: String },
last_name: { type: String },
roles: { type: Schema.Types.ObjectId, ref : 'Roles' },
}, {
timestamps: true
});
return mongooseClient.model('users', users);
};
Теперь, когда вам нужны разрешения роли на ресурс, вы просто ищете role_id и resource_id и проверяете, для каких разрешений установлено значение true в resources collection.
ПО промежуточного слоя авторизации
users.post('/', getAuth, someMethod)
Предполагая, что у вас есть какой-то токен в запросе, который идентифицирует пользователя, делающего сообщение, и прикрепляя экземпляр пользователя к объекту запроса, вы можете сделать это:
// pseudo code
getAuth = function (req, res, next) {
if(req.user) {
// query to get the user role's permissions for a resource
if(token){
// handle jwt token authenticity and decrypt payload
// get permission handler
db.getPerms({ role_id: req.user.role_id, resource_id: req.resource.id})
.then((perms) => {
var allow = false;
// mapping of methods to permissions
perms.forEach(function(perm){
if (req.method == "POST" && perms.create) allow = true;
else if (req.method == "GET" && perms.read) allow = true;
else if (req.method == "PUT" && perms.write) allow = true;
else if (req.method == "DELETE" && perm.delete) allow = true;
})
if (allow) next();
else {
res.status(403).send({error: 'access denied'});
}
})
.catch((err)=> {
//handle your reject and catch here
})
} else{
res.status(400).send({error: 'invalid token'})
}
Это некий псевдокод, показывающий, как можно написать промежуточное ПО аутентификации.
Это не самый оптимизированный фреймворк для реализации RBAC, поэтому я с нетерпением жду ваших отзывов 😄!!
Спасибо за аудиторию, и я надеюсь, что вы нашли эту статью полезной 🤗. Не стесняйтесь обращаться ко мне на Github, Twitter и LinkedIn. Ставьте лайк, комментируйте и делитесь 😌.
Первоначально опубликовано на https://blog.nextwebb.tech.