Я работаю с Node и Express для обработки запросов. Аутентификация на основе JWT и авторизация на основе ролей.
Итак, каждый раз, когда я нахожу в сети статью или учебное пособие о Express функциях промежуточного программного обеспечения авторизации, примеры слишком тривиальны, поскольку охватывают только такие запросы, как:
GET / выход из системы -------------- (1)
GET / админ-панель -------------- (3) )
Используя заголовок авторизации, содержащий JWT, каждый из этих URL легко фильтруется путем простого вычисления идентификатора запрашивающего пользователя для проверки существования в БД и, при необходимости, их роли. Все это делается в функции, размещенной между URL-адресом и целевым ресурсом, следовательно, промежуточным программным обеспечением. Затем:
(1) доступен для любого прошедшего проверку пользователя.
(2) доступен для любого прошедшего проверку пользователя, который также является администратором
Теперь для таких URL-адресов, как приведенный ниже, дополнительно может потребоваться проверка:
PATCH / users /: id -------------- (3)
GET / users /: id --- ----------- (4)
, поскольку администратор может просматривать и изменять профиль любого пользователя, но не администратор также может просматривать и изменять свой собственный профиль, затем:
(3) и (4) доступны либо для аутентифицированного администратора, либо для самого запрашивающего пользователя, что можно проверить, сравнив идентификатор, извлеченный из токена, с параметром :id
в запросе.
Пример:
//AuthorizationMiddleware.js
const Authentication = {
async authenticate(req, res, next) {
try {
const token = authorizationHeader.split(" ")[1];
if (!token) return res.status(400).send({ message: "Token was not provided" });
const decoded = jwt.verify(token, SECRET);
const userID = decoded.userID;
const user = (await db.query("SELECT * FROM my_user WHERE id = $1", [userID])).rows[0];
if (!user) {
return res.status(400).send({ message: "Token provided is invalid" });
}
req.user = { id: userID, role_id: user.role_id };
next();
} catch (error) {
console.error(error.toString());
return res.status(500).send('error');
}
},
async authorizeAdmin(req, res, next) {
const role_id = req.user.role_id;
if (role_id) {
if (role_id !== 1) {
return res.status(401).send('insufficient privileges');
}
next();
return;
}
}
};
export default Authentication;
И использование
//server.js
app.post("/api/v1/login", UserHandler.login);
app.post(
"/api/v1/users/new",
[AuthorizationMiddleware.authenticate, AuthorizationMiddleware.authorizeAdmin],
UserHandler.create
);
НО, что происходит, когда недостаточно просто знать идентификатор и роль пользователя, что, если URL похож на:
PATCH / posts /: id -------------- (5)
запрашивается? где только владелец сообщения (определенный пользователь) может изменять его.
В этом случае в параметрах нет информации о запрашивающем пользователе (:id
- это идентификатор сообщения), недостаточно знать, находятся ли они в БД, недостаточно знать, являются ли они администратором, нам нужно каким-то образом определить, связан ли идентификатор этого поста с с пользователем, который делает запрос, в БД.
Как это можно сделать в обработчике промежуточного программного обеспечения без потери его цель только обслуживать аутентификацию / авторизацию? без доступа к таблице сообщения, чтобы проверить владельца?
Надеюсь, я объяснил себе.
Спасибо