2012-02-22 11 views
21

Jakie są dobre strategie autoryzacji opartej na rolach w pliku express.js? Zwłaszcza z ekspresowym zasobem?Metoda autoryzacji opartej na grupach/regułach w plikach node.js i express.js

Z Express-resource brak ładowarki, więc myślę, że istnieją trzy opcje:

  1. używać middleware
  2. Przepuścić funkcję autoryzacji do zasobu i sprawdź każde żądanie zasobu oddzielnie
  3. Autoryzacja z każde żądanie zaraz po uwierzytelnieniu

Czy są jakieś inne rozwiązania?

Autoryzacja grupowa/oparta na rolach jest dość starodawnym podejściem. Czy istnieją nowsze metody kontroli dostępu? Jeśli nie, w jaki sposób autoryzację opartą na rolach można zastosować do pliku node.js? Gdzie przechowywać relacje między regułami (z NoSQL/CouchDB/Redis)?

Jako przykład, struktura:

/ 
    /forums 
    /forums/threads 

Każdy zasób z indeksu, nowe, tworzenie, edycja show, aktualizacji i zniszczyć. Niektóre osoby mogą edytować/usuwać itp. Wątki i fora, niektórzy nie powinni.

Odpowiedz

11

Connect-roles jest dość dobry, prosty i dokumentacja jest również bardzo jasne.

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'); 
} 
3

W wyrażeniu możesz dodać handler'a, który podpina każdego operatora (http://expressjs.com/guide.html#passing-route control), gdzie możesz przeprowadzić walidację warunków wstępnych. Tutaj możesz odzyskać rolę dla użytkownika i ograniczyć dostęp na podstawie czasownika HTTP (PUT, DELETE itp.) Lub adresu URL (param('op') to "edytuj" 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)); 
    } 
}); 
+0

Niestety, jak już wspomniano, że nie działa z Express-zasobów. – Patrick

32

Powiedziałbym, że trudno jest rozwiązać ten problem w czystym sposób przy użyciu Express zasobów, ponieważ nie pozwalają na trasie middleware specyficzne (przynajmniej nie w czystym sposób).

Wybrałbym podobny układ, jak moduł ekspresowego zasobu, ale kieruję go zwykłym starym ekspresowym. 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 

UPDATE: Ciągle trwają dyskusje dotyczące konkretnych tras middleware w wyraźnej-zasobu, np here. Przeważa pogląd wydaje się mieć tablicę na działanie, np .:

var forums = { 
    index: [ requireRole('foo'), function(req, res, next) { ... } ] 
}; 

Można spojrzeć poprzez wniosków pociągowych i zobaczyć czy jest coś można użyć. Rozumiem to oczywiście, jeśli nie czujesz się z tym dobrze. Jestem prawie pewny, że zobaczymy coś takiego w zasobach ekspresowych w przyszłości.

Jedynym rozwiązaniem można myślę, jest wzdłuż linii odpowiedź Jana Jongboom, co byłoby zamontować zasoby z wyraźną-zasobu, ale mają middleware załączeniu „zewnątrz”, że coś takiego:

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 ten wyciek adresów URL w każdym miejscu.

+0

Problemem jest to, że istnieje spora ilość zasobów i to dość czyste z wyraźną-zasobu. Zastanawiam się nad małym modułem, którego mogę użyć z app.use(), ale nie wiem jak to napisać. – Patrick

+0

Patrick, całkowicie się zgadzam. Zobacz moją aktualizację powyżej, aby uzyskać więcej dyskusji. Jest więcej żądań ściągania niż ta, którą przywołuję w związku z tym. Nie jestem tego pewien, ale mam wrażenie, że TJ będzie działać bardziej na express-resource, express-namespace i co po 3.0 jest na wyciągnięcie ręki, wydaje się być kilka zmian. –

2

Napisałem moduł jako pośrednie oprogramowanie pośredniczące do routingu. Działa dobrze z trasami ekspresowymi.

Gandalf on GitHub

+0

Dzięki @Patrick dla middleware. Czy istnieje dobry przykład na to, jak używać go z expressjs. Przykro mi, jeśli to brzmi jak pytanie noobów Jestem całkiem nowy dla nodejs i ekspresowych. Przykład będzie świetny dzięki – praneybehl

+0

@praneybehl Polecam, idąc z connect-roles lub podejście Linusa. Oprogramowanie pośrednie Gandalf jest nieaktualne. – Patrick

26

Badam to samo pytanie i natknąłem się na kilka dobrych modułów. Skupiłem się na pakiecie acl-node, który można znaleźć tutaj. https://github.com/optimalbits/node_acl.

Ten pakiet wydaje się implementować wzór ACL w bardzo zrozumiały sposób i zapewnił sposoby łatwej integracji z aplikacją węzła/ekspresu.

Po pierwsze, będziesz chciał 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 może mapować do rzeczywistych kont użytkowników, ale będą dziedziczyć wszystkie uprawnienia do roli użytkownika.

Uprawnienia dotyczące zasobów

  • tworzą
  • pokazać
  • aktualizacja
  • zniszczyć

lub swoich standardowych operacji CRUD.

Teraz, gdy zostały one zdefiniowane, możemy przyjrzeć się, jak byłoby wyglądać, aby ustawić acl za pomocą node-acl. Uwagi te pochodzą z dokumentacji

importu pakiet

var acl = require('acl'); 

Skonfiguruj backend. Moja aplikacja jest przy użyciu MongoDB, ale pakiet węzłów acl nie obsługuje inne mechanizmy przechowywania

acl = new acl(new acl.mongodbBackend(dbInstance, prefix)); 

moja aplikacja korzysta mongoose tak dbInstance zostanie zastąpiony mongoose.connection.db

Teraz dodajemy nasze role ACL. W node-acl role są tworzone przez nadanie im uprawnień. Jej jak zabijając dwie pieczenie na jednym ogniu (bez ptaki rzeczywiście szkodzi)

acl.allow('admin', ['/', '/forum', '/forum/threads'], '*'); 
acl.allow('public', ['/', '/forum', '/forum/threads'], 'show'); 
acl.allow('user', ['/', '/forum', '/forum/threads'], ['create', 'show']); 

Załóżmy nowy zasób jest tworzony przez Jana, dodamy nowy rekord, który pozwala John również aktualizować i usuwać tego zasobu.

acl.allow('john', ['/forum/threads/abc123'], ['update', 'delete']); 

Moja aplikacja również używa wyrażenia, więc użyję metody routingu pośredniego do sprawdzenia tras.W mojej konfiguracji routingu, chciałbym dodać linię

w większości ekspresowych konfiguracjach, to wygląda na poz

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) {...}); 

Kiedy żadne parametry są przekazywane, to sprawdzić, czy rola jest określona w req.userId zezwolono na wykonanie metody http na zidentyfikowanym zasobie, ale na trasie.

W tym przykładzie metoda http jest poczta, ale będzie to zrobić to samo dla każdego http idenitified w danej konfiguracji.

Nasuwa się pytanie o uprawnieniach określonych wcześniej. Aby odpowiedzieć na te pytania, trzeba by zmienić uprawnienia od

  • tworzyć
  • pokazać
  • aktualizacja
  • zniszczyć

do konwencjonalnego

  • postu
  • dostać
  • umieścić
  • usuwać

Chociaż ten przykład pokazuje wszystko na sztywno, lepszym rozwiązaniem jest mieć interfejs zarządzania dla swoich uprawnień, aby mogły być tworzone, czytać, zaktualizowane i usunięte dynamicznie, bez konieczności zmienić swój kod.

Lubię Węzeł-ACL wtyczek podejście, gdyż pozwala na bardzo drobnoziarnistych zadań pozwolenie-role stosując bardzo proste i elastyczne API. W ich dokumentacji jest dużo więcej, moje przykładowe pokazy były w pakiecie.

Mam nadzieję, że to pomaga.

+0

co jest publiczne? Mam trudności z pozbyciem się zasobów łonowych – danielad

Powiązane problemy