2013-10-28 4 views
9

Diese Frage bezieht sich auf das angular-app Projekt und die Art, wie es Benutzer authentifiziert.Angular-App, Authentifizierung und Reihenfolge der Resolver in (ui-) Router

Die ursprüngliche Implementierung schützt den Zugriff auf einige URLs mithilfe der Auflösungsklausel auf dem Router. Das sieht so aus:

$routeProvider.when('/projects', { 
templateUrl:'projects/projects-list.tpl.html', 
controller:'ProjectsViewCtrl', 
resolve:{ 
    projects:['Projects', function (Projects) { 
    //TODO: fetch only for the current user 
    return Projects.all(); 
    }], 
    authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser 
} 

});

Die Ansicht wird erst gerendert, wenn ein Benutzer authentifiziert wurde und Projekte abgerufen wurden (um ein Flimmern zu vermeiden). Wenn ein Benutzer nicht authentifiziert wird, erscheint ein Anmelde-Popup, und nachdem der Benutzer es übermittelt hat, wird das Versprechen gelöst und eine angeforderte Seite angezeigt. Das funktioniert gut, wenn auth nicht für den Aufruf von Projects.all() benötigt wird.

Hier ist das Protokoll der Serveraufrufe:

127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /projects HTTP/1.1" 200 739 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" 
Unauthenticated 
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /current-user HTTP/1.1" 200 24 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" 
Unauthenticated 
Unauthenticated 
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /current-user HTTP/1.1" 200 24 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" 
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:47 GMT] "GET /databases/angular_app/collections/projects?q=%7B%7D HTTP/1.1" 200 10 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" 
Unauthenticated 
127.0.0.1 - - [Mon, 28 Oct 2013 11:15:59 GMT] "POST /login HTTP/1.1" 200 161 "http://localhost:3000/projects" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:24.0) Gecko/20100101 Firefox/24.0" 

Der Aufruf von angular_app/Sammlungen/Projekte gilt auch für nicht authentifizierte Benutzer.

In meinem Fall habe ich den folgenden Code:

$stateProvider 
    .state('root.tickets', { 
     url: '/tickets', 
     views: { 
      '[email protected]': { 
       templateUrl: 'tickets/tickets-list.tpl.html', 
       controller:'TicketsViewCtrl', 
       resolve:{ 
        ticketsy: ['Restangular', function (Restangular) { 
        //Call to tickets must be authenticated 
        return Restangular.all('tickets').getList(); 
        }], 
        authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser 
       } 
      } 
     } 

Der Unterschied ist (außer ich ui-Router und Restangular verwenden), dass der API-Aufruf authentifiziert werden muss. Das Serverprotokoll sieht so aus:

[28/Oct/2013 05:50:15] "GET /api/tickets/ HTTP/1.1" 403 59 
[28/Oct/2013 05:50:15] "GET/HTTP/1.1" 200 963 
[28/Oct/2013 05:50:16] "GET /api/current-user/ HTTP/1.1" 200 14 
[28/Oct/2013 05:50:16] "GET /api/tickets HTTP/1.1" 301 0 
[28/Oct/2013 05:50:16] "GET /api/tickets/ HTTP/1.1" 403 59 
[28/Oct/2013 05:50:22] "POST /api/login/ HTTP/1.1" 200 120 

Hinweis 403 Statuscode hier. Der Effekt ist, dass der Benutzer das Anmelde-Popup sieht, authentifiziert, aber dann eine leere Seite sieht. Ich nehme an, dies liegt daran, dass das Abrufen von Versprechen fehlgeschlagen ist.

Meine Frage ist - ist es irgendwie möglich, Reihenfolge der Versprechen zu erzwingen? Ich möchte zuerst überprüfen, ob der Benutzer authentifiziert ist, dann einen Anruf an das Backend usw. senden. Oder gibt es eine andere Lösung, die ich hier verwenden kann? Ich lerne Angular so, selbst wenn es eine einfache Lösung gibt, ist es für mich nicht offensichtlich.

+0

'securityAuthorizationProvider.requireAuthenticatedUser', das ist eine Eigenschaft oder Funktion? – Chandermani

+0

Es ist eine Funktion. Siehe: https://github.com/angular-app/angular-app/blob/master/client/src/common/security/authorization.js#L21 – eXt

Antwort

15

Ich liebe die Verwendung der Resolver-Muster, aber finde es sehr schwierig, diese Art von Dingen in eckigen Router zu tun.

eine Lösung ist das Ergebnis des AuthenticatedUser Resolver in den API-Aufruf Resolver Sie wie geschützt werden sollen, um Abhängigkeits zu injizieren:

$stateProvider 
    .state('root.tickets', { 
     url: '/tickets', 
     views: { 
      '[email protected]': { 
       templateUrl: 'tickets/tickets-list.tpl.html', 
       controller:'TicketsViewCtrl', 
       resolve:{ 
        authenticatedUser: securityAuthorizationProvider.requireAuthenticatedUser, 
        ticketsy: function (Restangular, authenticatedUser) { 
        //Call to tickets must be authenticated 
        return Restangular.all('tickets').getList(); 
        } 
       } 
      } 
     } 

die Resolvern Auf diese Weise wird in einer Kette laufen (AuthenticatedUser -> ticketsy) statt asynchron auf einmal.

Ich hoffe, das half .. wünschte, es gäbe einen besseren Weg, es zu tun .. das ist, warum ich suche durch Stapelüberlauf.

+0

Dies funktionierte perfekt für mich in einer Situation ähnlich wie bei @eXt. – JDWardle

+0

arbeitet nicht mit Winkel 1.2.19. Ich bekomme immer einen "unbekannten Provider authenticatedUserProvider". Fehle ich etwas? –

+0

@ Cétia Es ist, weil die eingereichte Antwort UI Router und nicht der Angular-Router verwendet. Bis spät, aber besser spät als nie. :) –

0

Haben Sie so etwas versucht.

return securityAuthorizationProvider.requireAuthenticatedUser().then(function() { 
    return Restangular.all('tickets').getList(); 
}); 

Grundsätzlich requireAuthenticatedUser gibt ein Versprechen, so dass Sie es mit dem Aufruf von Restangular Call-Kette können.

+0

Ich habe das versucht, aber danach weder die Seite gerendert noch irgendwelche Fehler wird ausgelöst. Seltsam. – eXt