В настоящее время я использую экспресс в качестве бэкэнда для своего приложения реакции. Чтобы защитить некоторые маршруты, я использую паспорт JWT, чтобы гарантировать, что пользователи вошли в систему и имеют действительный токен для доступа к различным частям приложения.
У меня может быть несколько маршрутов, доступ к которым могут получить все пользователи, а доступ к ним могут иметь только определенные пользователи. Например:
/api/online
доступно для всех, кто вошел в систему.
/api/users/
должны быть доступны только пользователям с особыми разрешениями.
Эти разрешения предварительно установлены в документе MongoDB пользователя в виде массива.
Когда пользователи входят в систему, к их токену прикрепляется следующая полезная нагрузка:
const payload = {
id: user.id,
name: user.name,
permissions: user.permissions
};
Идентификатор соответствует их идентификатору документа MongoDB, а разрешения извлекаются непосредственно из их документа и сохраняются в их токене полезной нагрузки. Они точно определяют, к каким маршрутам имеет доступ пользователь.
Затем я настраиваю паспорт следующим образом:
passport.use(
new JwtStrategy(opts, (jwt_payload, done) => {
if (!userCache[jwt_payload.id])
User.findById(jwt_payload.id)
.then(user => {
if (user) {
userCache[jwt_payload.id] = user;
setTimeout(() => {
delete userCache[jwt_payload.id]
}, 60 * 60 * 1000);//make sure data is up to date by the hour
return done(null, user);
}
return done(null, false);
})
.catch(err => {
console.log(err)
});
else done(null, userCache[jwt_payload.id]);
})
);
Не беспокойтесь о моей системе кеширования, я планирую улучшить ее, чтобы она автоматически обновлялась при изменении модели Users.
Моя проблема в том, что в этом методе позволяет реализовать паспорт, нет способа проверить фактический маршрут, к которому осуществляется доступ. jwt_payload
содержит массив полномочий, который я установил ранее, но он бесполезен, так как я не могу проверить маршрут, чтобы убедиться, что пользователь авторизован. Вот как я сейчас авторизую маршруты:
app.get('/api/online', passport.authenticate('jwt', {session: false}), (req, res) => {//fetch the current amount of people online
res.setHeader('Content-Type', 'text/plain');
res.send(userServer.connectionCount.toString());
});
Это прекрасно работает, так как этот маршрут должен быть доступен всем, кто вошел в систему, однако, что если я хочу использовать маршрут /api/users
? Я не знаю, как передать специальную строку, чтобы сказать «этот маршрут должен быть разрешен только пользователям с разрешением x
.
Есть предложения?
Я пробовал
api.use('/api/users',(req,res,next)=>{})
но поиск способа расшифровки токена аутентификации без паспорта звучит немного лишним и добавляет сложности, которую должен решить паспорт. Кроме того, заставить клиента вручную передавать свои разрешения для решения предыдущей проблемы - это огромный риск для безопасности, поскольку любой может просто создать свои разрешения и прикрепить его к телу запроса.
- Несколько паспортов с разными конфигами. Затем, позволяя мне переходить к различным маршрутам
passport.authenticate
. Казалось невозможным, или я делал что-то не так.
Спасибо.