javascript - Jak łączyć uwierzytelnianie jwt z ACL
Udało mi się zaimplementować Passport używając strategii JWT i działa to dobrze. Moje trasy chronione przez JWT wyglądają tak...
app.get('/thingThatRequiresLogin/:id', passport.authenticate('jwt', { session: false }), thingThatRequiresLogin.findById);
Teraz muszę ograniczyć dostęp do niektórych rzeczy tylko dla zalogowanych użytkowników należących do określonej roli. Chciałbym móc wyrazić to w taki sposób:
app.get('/thingThatRequiresLogin/:id', MAGIC, thingThatRequiresLogin.findById);
Gdzie MAGIC=wymaga zalogowanych użytkowników, ale tylko tych z rolą x lub y
node_acl wydaje się być dobrym rozwiązaniem i rozumiem to do pewnego stopnia, ale potem znajduję to w dokumentacji...
Możemy chronić zasób w ten sposób:
app.put('/blogs/:id', acl.middleware(), function(req, res, next){…}
Middleware będzie chronić zasób o nazwie podanej w req.url, wybierze użytkownika z req.session.userId i sprawdzi uprawnienia dla req.method, więc powyższe byłoby równoważne z czymś takim:
Jak mogę połączyć to z moją strategią JWT? Moim jedynym pomysłem jest zrezygnowanie z middleware node_acl i zamiast tego dodanie kodu do sprawdzania ACL do mojej strategii JWT. Ale tutaj napotykam problemy. Moja funkcja JWT wygląda tak:
passport.use(new JwtStrategy(jwtOptions, function(jwt_payload, done) {
User.findOne({id: jwt_payload.sub}, function(err, user) {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
// or you could create a new account
}
});
}));
Zgodnie z node_acl, mogę zapytać o coś takiego...
acl.isAllowed('jsmith', 'blogs', ['edit','view','delete'])
Czy więc mogę (czy powinienem?) zmienić moją JwtStrategy, aby powiedzieć coś w stylu...
if (user && acl.isAllowed(user.username, 'blogs', ['edit','view','delete']) {
// ...
Jeśli tak, jak ta funkcja będzie wiedziała o nazwie zasobu 'blogs' i uprawnieniach ['edit' itd.]? Są one znane w momencie definiowania trasy, ale myślę, że potrzebuję ich w funkcji strategii. Czy podchodzę do tego całkowicie źle? Czy ktoś mógłby pokazać mi właściwy sposób?
Odpowiedź #1
app.get('/thingThatRequiresLogin/:id',
[
passport.authenticate('jwt', { session: false }),
acl.middleware( 1, getUserId )
],
thingThatRequiresLogin.findById);
czerpiąc wskazówkę z tego gista: https://gist.github.com/danwit/e0a7c5ad57c9ce5659d2 oraz dokumentacji node_acl na npm: https://www.npmjs.com/package/acl#middleware acl.middleware przyjmuje trzy opcjonalne argumenty: acl.middleware(numPathComponents, userId, permissions)
numPathComponents: 1/aby wybrać ścieżkę thingThatRequiresLogin
userId: getUserId //getUserId to funkcja, która zwraca userId
Mam nadzieję, że to pomoże
