Podejście autoryzacyjne oparte na grupach / regułach w węźle.js i express.js
Jakie są dobre strategie autoryzacji opartej na rolach w programie express.js? Zwłaszcza z express-resource?
Z Express-resource nie ma obsługi, więc myślę, że są trzy opcje:
- Użyj middleware
- przekazać funkcję autoryzacji do zasobu i sprawdzić każde żądanie zasobu oddzielnie
- sprawdzanie autoryzacji przy każdym żądaniu zaraz po uwierzytelnieniu
Czy są jakieś inne rozwiązania?
Group/Role-based authorization to dość antyczne podejście. Czy istnieją nowsze metody kontroli dostępu? Jeśli nie, w jaki sposób można zastosować autoryzację opartą na rolach do węzła.js? Gdzie przechowywać relacje reguły grupy (z NoSQL / CouchDB / Redis)?
Jako przykład struktura:
/
/forums
/forums/threads
Każdy zasób z indeksem, nowy, tworzyć, pokazywać, edytować aktualizować i niszczyć. Niektóre osoby mogą edytować / usuwać itp. wątki i fora, niektórzy nie powinni.
5 answers
Connect-roles jest całkiem dobry, prosty i dokumentacja jest również bardzo przejrzysta.
var user = roles;
app.get('/profile/:id', user.can('edit profile'), function (req, res) {
req.render('profile-edit', { id: req.params.id });
})
app.get('/admin', user.is('admin'), function (req, res) {
res.render('admin');
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-11 09:50:56
Powiedziałbym, że trudno jest rozwiązać to w czysty sposób za pomocą express-resource, ponieważ nie pozwala to na użycie oprogramowania pośredniczącego specyficznego dla trasy (przynajmniej nie w czysty sposób).
Wybrałbym podobny układ jak moduł express-resource, ale przekierowywałbym go za pomocą zwykłego starego expressa. Coś takiego:
// Resource
var forum = {
index: // ...
show: // ...
create: // ...
update: // ...
destroy: // ...
};
// Middleware
var requireRole = function(role) {
return function(req, res, next) {
if('user' in req.session && req.session.user.role === role)
next();
else
res.send(403);
}
};
// Routing
app.get('/forums', forum.index);
app.get('/forums/:id', forum.show);
app.post('/forums', requireRole('moderator'), forum.create); // Only moderators can create forums
app.delete('/forums/:id', requireRole('admin'), forum.destroy); // Only admins can delete forums
Aktualizacja: trwają dyskusje na temat specyficznego dla trasy oprogramowania pośredniego w express-resource, np. tutaj . Panujący pogląd wydaje się mieć tablica na akcję, np.:
var forums = {
index: [ requireRole('foo'), function(req, res, next) { ... } ]
};
Możesz przejrzeć żądania pull i zobaczyć, czy jest coś, czego możesz użyć. Rozumiem to, jeśli nie czujesz się z tym komfortowo. Jestem pewien, że coś takiego zobaczymy w express-resource w przyszłości.
Jedyne inne rozwiązanie, jakie mogę wymyślić, to odpowiedź Jana Jongbooma, która polegałaby na zamontowaniu zasobów za pomocą express-resource, ale mieć dołączone oprogramowanie pośredniczące "Na Zewnątrz" to coś w stylu:
app.delete('*', requireRole('admin')); // Only admins are allowed to delete anything
app.put('/forums/*', requireRole('moderator')); // Only moderators are allowed to update forums
Ale żałuję, że to wycieka adresy URL wszędzie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-28 14:12:56
Badałem to samo pytanie i natknąłem się na kilka dobrych modułów. Skupiłem się na pakiecie node-acl, który można znaleźć tutaj. https://github.com/optimalbits/node_acl .
Wydaje się, że ten pakiet zaimplementował wzorzec ACL w bardzo zrozumiały sposób i zapewnił sposoby łatwej integracji go z aplikacją node/express.
Najpierw musisz zdefiniować swoje zasoby, role i uprawnienia.
Na przykład, zasoby mogą być:
/
/forums
/forums/threads
Role mogą być
public
admin
user
john
jane
W tym przykładzie role john i jane mogą mapować do rzeczywistych kont użytkowników, ale odziedziczą wszystkie uprawnienia do roli użytkownika.
Uprawnienia do zasobów
- Utwórz
- Pokaż
- update
- destroy
Teraz, gdy zostały one zdefiniowane, możemy przyjrzeć się, jak wyglądałoby skonfigurowanie acl używając node-acl. Uwagi te pochodzą z dokumentacji
Importuj pakiet
var acl = require('acl');
Skonfiguruj swój backend. Moja aplikacja używa mongodb, ale pakiet node-acl obsługuje inne mechanizmy przechowywania]}
acl = new acl(new acl.mongodbBackend(dbInstance, prefix));
Moja aplikacja używa mangusty, więc dbInstance zostanie zastąpiony mangustą.połączenie.db
Teraz dodajmy nasze role do ACL. W node-acl role są tworzone przez nadanie im uprawnień. To jak zabicie dwóch ptaków jednym kamieniem (żadne ptaki nie są w rzeczywistości hurt)
acl.allow('admin', ['/', '/forum', '/forum/threads'], '*');
acl.allow('public', ['/', '/forum', '/forum/threads'], 'show');
acl.allow('user', ['/', '/forum', '/forum/threads'], ['create', 'show']);
Załóżmy, że nowy zasób został stworzony przez Johna, dodamy nowy rekord, który pozwala Johnowi również aktualizować i usuwać ten zasób.
acl.allow('john', ['/forum/threads/abc123'], ['update', 'delete']);
Moja aplikacja również używa express, więc użyję podejścia routing middleware do sprawdzania tras. W mojej konfiguracji routingu dodałbym linię
W większości konfiguracji ekspresowych wygląda to tak dla pos
app.post('/', acl.middleware(), function(req, res, next) {...});
app.post('/forums', acl.middleware(), function(req, res, next) {...});
app.post('/forums/:forumId', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads', acl.middleware(), function(req, res, next) {...});
app.post('/forums/threads/:threadId', acl.middleware(), function(req, res, next) {...});
Gdy nie zostaną przekazane żadne parametry, sprawdzi to, czy rola zdefiniowana w req.userId może wykonywać metodę http na zidentyfikowanym zasobie, ale na trasie.
W tym przykładzie metoda http to post, ale zrobi to samo dla każdego identyfikowalnego http w Twojej konfiguracji.
Nasuwa się pytanie o uprawnienia zdefiniowane wcześniej. Aby odpowiedzieć na te pytania, musielibyśmy zmienić uprawnienia z
- Utwórz
- Pokaż
- update
- destroy
Do konwencjonalne
- post
- get
- put
- Usuń
Chociaż ten przykład pokazuje wszystko zakodowane na twardo, lepszą praktyką jest posiadanie interfejsu zarządzania uprawnieniami, aby mogły być tworzone, odczytywane, aktualizowane i usuwane dynamicznie bez konieczności modyfikowania kodu.
Podoba mi się podejście wtyczek node-acl, ponieważ pozwala na bardzo drobnoziarniste przypisanie uprawnień do ról przy użyciu bardzo prostego i elastycznego api. Tam jest o wiele więcej w ich dokumentacji, mój przykład pokazuje, że jestem z pakietem.
Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-04 21:17:13
W Expressie możesz dodać obsługę, która łączy się z każdym operatorem (http://expressjs.com/guide.html#passing-route control), gdzie można wykonać walidację warunków wstępnych. Tutaj możesz pobrać rolę dla użytkownika i ograniczyć dostęp na podstawie czasownika HTTP (PUT, DELETE, itp.)lub URL (param('op')
to' edit ' lub tak).
app.all('/user/:id/:op?', function(req, res, next){
req.user = users[req.params.id];
if (req.user) {
next();
} else {
next(new Error('cannot find user ' + req.params.id));
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-22 11:22:42
Napisałem moduł jako nie-jawne routing middleware. Dobrze współpracuje z trasami ekspresowymi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-14 08:31:33