AngularJS UI-Router login authentication

W związku z tym, że router nie działa w trybie"ui-router", nie można go używać w trybie "UI-router".]}

Buduję aplikację internetową, która składa się z dwóch sekcji. Pierwsza sekcja to strona główna z widokami logowania i rejestracji, a druga sekcja to Pulpit nawigacyjny (po pomyślnym zalogowaniu).

Utworzyłem index.html dla sekcji home z jej aplikacją angular oraz ui-router config do obsługi /login i /signup views, i jest jeszcze jeden plik dashboard.html dla sekcji dashboard z jej aplikacją i konfiguracją ui-router do obsługi wielu widoków podrzędnych.

Teraz skończyłem sekcję dashboard i nie wiem, jak połączyć dwie sekcje z ich różnymi aplikacjami kątowymi. Jak mogę powiedzieć aplikacji home, aby przekierowała do aplikacji dashboard?

Author: Ahmed Hashem, 2014-03-20

10 answers

Jestem w trakcie tworzenia ładniejszego demo, a także czyszczenia niektórych z tych usług w użyteczny moduł, ale oto, co wymyśliłem. To skomplikowany proces, aby obejść pewne zastrzeżenia, więc trzymaj się. Musisz to rozbić na kilka kawałków.

Spójrz na to plunk .

Po pierwsze, potrzebujesz usługi do przechowywania tożsamości użytkownika. Nazywam to principal. Można sprawdzić, czy użytkownik jest zalogowany, a na żądanie może rozwiąż obiekt, który reprezentuje podstawowe informacje o tożsamości użytkownika. Może to być wszystko, czego potrzebujesz, ale najważniejsze będzie wyświetlana nazwa, nazwa użytkownika, ewentualnie e-mail i role, do których należy użytkownik (jeśli dotyczy to Twojej aplikacji). Dyrektor ma również metody sprawdzania ról.

.factory('principal', ['$q', '$http', '$timeout',
  function($q, $http, $timeout) {
    var _identity = undefined,
      _authenticated = false;

    return {
      isIdentityResolved: function() {
        return angular.isDefined(_identity);
      },
      isAuthenticated: function() {
        return _authenticated;
      },
      isInRole: function(role) {
        if (!_authenticated || !_identity.roles) return false;

        return _identity.roles.indexOf(role) != -1;
      },
      isInAnyRole: function(roles) {
        if (!_authenticated || !_identity.roles) return false;

        for (var i = 0; i < roles.length; i++) {
          if (this.isInRole(roles[i])) return true;
        }

        return false;
      },
      authenticate: function(identity) {
        _identity = identity;
        _authenticated = identity != null;
      },
      identity: function(force) {
        var deferred = $q.defer();

        if (force === true) _identity = undefined;

        // check and see if we have retrieved the 
        // identity data from the server. if we have, 
        // reuse it by immediately resolving
        if (angular.isDefined(_identity)) {
          deferred.resolve(_identity);

          return deferred.promise;
        }

        // otherwise, retrieve the identity data from the
        // server, update the identity object, and then 
        // resolve.
        //           $http.get('/svc/account/identity', 
        //                     { ignoreErrors: true })
        //                .success(function(data) {
        //                    _identity = data;
        //                    _authenticated = true;
        //                    deferred.resolve(_identity);
        //                })
        //                .error(function () {
        //                    _identity = null;
        //                    _authenticated = false;
        //                    deferred.resolve(_identity);
        //                });

        // for the sake of the demo, fake the lookup
        // by using a timeout to create a valid
        // fake identity. in reality,  you'll want 
        // something more like the $http request
        // commented out above. in this example, we fake 
        // looking up to find the user is
        // not logged in
        var self = this;
        $timeout(function() {
          self.authenticate(null);
          deferred.resolve(_identity);
        }, 1000);

        return deferred.promise;
      }
    };
  }
])

Po drugie, potrzebujesz usługi, która sprawdza stan, do którego użytkownik chce się udać, upewnia się, że jest zalogowany (jeśli to konieczne; nie jest to konieczne do logowania, resetowania hasła itp.), a następnie sprawdza rolę (jeśli aplikacja tego potrzebuje). Jeśli nie są uwierzytelnione, wyślij je na stronę logowania. Jeśli są uwierzytelnione, ale nie sprawdzają roli, wyślij je na stronę Odmowa dostępu. Nazywam tę usługę authorization.

.factory('authorization', ['$rootScope', '$state', 'principal',
  function($rootScope, $state, principal) {
    return {
      authorize: function() {
        return principal.identity()
          .then(function() {
            var isAuthenticated = principal.isAuthenticated();

            if ($rootScope.toState.data.roles
                && $rootScope.toState
                             .data.roles.length > 0 
                && !principal.isInAnyRole(
                   $rootScope.toState.data.roles))
            {
              if (isAuthenticated) {
                  // user is signed in but not
                  // authorized for desired state
                  $state.go('accessdenied');
              } else {
                // user is not authenticated. Stow
                // the state they wanted before you
                // send them to the sign-in state, so
                // you can return them when you're done
                $rootScope.returnToState
                    = $rootScope.toState;
                $rootScope.returnToStateParams
                    = $rootScope.toStateParams;

                // now, send them to the signin state
                // so they can log in
                $state.go('signin');
              }
            }
          });
      }
    };
  }
])

Teraz wszystko, co musisz zrobić, to wsłuchać się w ui-router ' s $stateChangeStart. Daje to szansę na sprawdzenie aktualnego stanu, stanu, do którego chcą przejść, i wstaw sprawdzenie autoryzacji. Jeśli się nie powiedzie, możesz anulować Przejście trasy lub zmienić na inna trasa.

.run(['$rootScope', '$state', '$stateParams', 
      'authorization', 'principal',
    function($rootScope, $state, $stateParams, 
             authorization, principal)
{
      $rootScope.$on('$stateChangeStart', 
          function(event, toState, toStateParams)
      {
        // track the state the user wants to go to; 
        // authorization service needs this
        $rootScope.toState = toState;
        $rootScope.toStateParams = toStateParams;
        // if the principal is resolved, do an 
        // authorization check immediately. otherwise,
        // it'll be done when the state it resolved.
        if (principal.isIdentityResolved()) 
            authorization.authorize();
      });
    }
  ]);

Trudną częścią śledzenia tożsamości użytkownika jest wyszukanie jej, jeśli już uwierzytelniłeś (powiedzmy, że odwiedzasz stronę po poprzedniej sesji i zapisałeś token auth w pliku cookie, a może odświeżyłeś stronę lub upuściłeś na adres URL z linku). Ze względu na sposób działania ui-router, musisz raz rozwiązać swoją tożsamość, zanim twoje auth sprawdzi. Możesz to zrobić za pomocą opcji resolve w konfiguracji stanu. Mam jedno państwo macierzyste dla strona, z której dziedziczą wszystkie stany, co zmusza dyrektora do rozwiązania, zanim cokolwiek się stanie.

$stateProvider.state('site', {
  'abstract': true,
  resolve: {
    authorize: ['authorization',
      function(authorization) {
        return authorization.authorize();
      }
    ]
  },
  template: '<div ui-view />'
})
Jest jeszcze jeden problem... Dzwoni się tylko raz. Po wypełnieniu obietnicy dotyczącej wyszukiwania tożsamości nie zostanie ponownie uruchomiony delegat resolve. Musimy więc wykonać twoje auth checks w dwóch miejscach: raz zgodnie z Twoją obietnicą tożsamości rozwiązanie w resolve, które obejmuje pierwsze ładowanie aplikacji, i raz w $stateChangeStart, jeśli zostało zrobione rozwiązanie, które obejmuje za każdym razem, gdy poruszasz się po Stanach. OK, więc co zrobiliśmy do tej pory?
  1. sprawdzamy, kiedy aplikacja się ładuje, jeśli użytkownik jest zalogowany.
  2. śledzimy informacje o zalogowanym użytkowniku.
  3. przekierowujemy je do stanu logowania dla stanów, które wymagają zalogowania użytkownika.
  4. przekierowujemy ich do stanu odmowy dostępu, jeśli nie mają autoryzacji dostępu do niego.
  5. mamy mechanizm przekierowujący użytkowników z powrotem do pierwotnego stanu oni wymagane, jeśli potrzebowaliśmy ich do logowania.
  6. możemy wylogować użytkownika (musi być podłączony do dowolnego kodu klienta lub serwera, który zarządza Twoim biletem auth).
  7. My nie musimy wysyłać użytkowników z powrotem do strony logowania za każdym razem, gdy przeładowują przeglądarkę lub upuszczają link.

Co dalej? Możesz zorganizować swoje stany w regiony, które wymagają zalogowania. Możesz wymagać uwierzytelnionych / autoryzowanych użytkowników, dodając data z roles do tych stanów (lub ich rodzica, jeśli chcesz użyć dziedziczenia). Tutaj ograniczamy zasób do administratorów:

.state('restricted', {
    parent: 'site',
    url: '/restricted',
    data: {
      roles: ['Admin']
    },
    views: {
      'content@': {
        templateUrl: 'restricted.html'
      }
    }
  })

Teraz możesz kontrolować stan po stanie, co użytkownicy mogą uzyskać dostęp do trasy. Jakieś inne obawy? Może zmienianie tylko części widoku w zależności od tego, czy są zalogowani? Nie ma sprawy. Użyj principal.isAuthenticated() lub nawet principal.isInRole() z dowolnym z wielu sposobów warunkowego wyświetlania szablonu lub elementu.

Najpierw wstrzyknij principal do kontrolera lub cokolwiek innego, i przyklej go do zakresu, dzięki czemu można go łatwo używać w widoku:

.scope('HomeCtrl', ['$scope', 'principal', 
    function($scope, principal)
{
  $scope.principal = principal;
});

Pokaż lub ukryj element:

<div ng-show="principal.isAuthenticated()">
   I'm logged in
</div>
<div ng-hide="principal.isAuthenticated()">
  I'm not logged in
</div>

Itd. i tak dalej. Tak czy inaczej, w Twojej przykładowej aplikacji, będziesz miał Stan strony głównej, który pozwoliłby nieautoryzowanym użytkownikom wpaść. Mogą mieć linki do Stanów logowania lub rejestracji lub mieć te formularze wbudowane na tej stronie. Cokolwiek ci pasuje.

Strony dashboardu mogą dziedziczyć od stanu, który wymaga zalogowania użytkowników i, powiedzmy, być User rola członka. Wszystkie autoryzacje, o których rozmawialiśmy, wypływałyby stamtąd.
 608
Author: moribvndvs,
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
2016-06-08 16:21:44

Dotychczas opublikowane rozwiązania są moim zdaniem niepotrzebnie skomplikowane. Jest prostszy sposób. dokumentacja ui-router mówi listen to $locationChangeSuccess and use $urlRouter.sync() to check a state transition, halt it, or wznowienie it. Ale nawet to nie działa.

Są jednak dwie proste alternatywy. Wybierz jeden:

Rozwiązanie 1: listening on $locationChangeSuccess

Można słuchać $locationChangeSuccess i można tam wykonać jakąś logikę, nawet asynchroniczną. Na podstawie tej logiki, możesz pozwolić funkcji zwrócić undefined, co spowoduje, że przejście stanu będzie kontynuowane jak zwykle, lub możesz zrobić $state.go('logInPage'), jeśli użytkownik musi być uwierzytelniony. Oto przykład:

angular.module('App', ['ui.router'])

// In the run phase of your Angular application  
.run(function($rootScope, user, $state) {

  // Listen to '$locationChangeSuccess', not '$stateChangeStart'
  $rootScope.$on('$locationChangeSuccess', function() {
    user
      .logIn()
      .catch(function() {
        // log-in promise failed. Redirect to log-in page.
        $state.go('logInPage')
      })
  })
})

Należy pamiętać, że w rzeczywistości nie zapobiega to ładowaniu się stanu docelowego, ale przekierowuje do strony logowania, jeśli użytkownik jest nieautoryzowany. To w porządku, ponieważ prawdziwa ochrona jest na serwerze.

Rozwiązanie 2: użycie stanu resolve

W tym roztworze stosuje się ui-router funkcja resolve .

Zasadniczo odrzucasz obietnicę w resolve, Jeśli Użytkownik nie jest uwierzytelniony, a następnie przekierowujesz go na stronę logowania.

Oto Jak to jest:

angular.module('App', ['ui.router'])

.config(
  function($stateProvider) {
    $stateProvider
      .state('logInPage', {
        url: '/logInPage',
        templateUrl: 'sections/logInPage.html',
        controller: 'logInPageCtrl',
      })
      .state('myProtectedContent', {
        url: '/myProtectedContent',
        templateUrl: 'sections/myProtectedContent.html',
        controller: 'myProtectedContentCtrl',
        resolve: { authenticate: authenticate }
      })
      .state('alsoProtectedContent', {
        url: '/alsoProtectedContent',
        templateUrl: 'sections/alsoProtectedContent.html',
        controller: 'alsoProtectedContentCtrl',
        resolve: { authenticate: authenticate }
      })

    function authenticate($q, user, $state, $timeout) {
      if (user.isAuthenticated()) {
        // Resolve the promise successfully
        return $q.when()
      } else {
        // The next bit of code is asynchronously tricky.

        $timeout(function() {
          // This code runs after the authentication promise has been rejected.
          // Go to the log-in page
          $state.go('logInPage')
        })

        // Reject the authentication promise to prevent the state from loading
        return $q.reject()
      }
    }
  }
)

W przeciwieństwie do pierwszego rozwiązania, rozwiązanie to faktycznie zapobiega ładowaniu się stanu docelowego.

 120
Author: M.K. Safi,
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
2017-05-26 17:13:11

Najprostszym rozwiązaniem jest użycie $stateChangeStart i event.preventDefault(), aby anulować zmianę stanu, gdy użytkownik nie jest uwierzytelniony i przekierować go do stanu auth , który jest stroną logowania.

angular
  .module('myApp', [
    'ui.router',
  ])
    .run(['$rootScope', 'User', '$state',
    function ($rootScope, User, $state) {
      $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        if (toState.name !== 'auth' && !User.authenticaded()) {
          event.preventDefault();
          $state.go('auth');
        }
      });
    }]
  );
 42
Author: sebest,
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
2016-06-29 05:46:00

Myślę, że potrzebujesz service, które obsługują proces uwierzytelniania (i jego przechowywanie).

W tym serwisie będziesz potrzebował kilku podstawowych metod :

  • isAuthenticated()
  • login()
  • logout()
  • itd ...

Ta usługa powinna być wtryskiwana do kontrolerów każdego modułu:

  • w sekcji Pulpitu nawigacyjnego użyj tej usługi, aby sprawdzić, czy użytkownik jest uwierzytelniony (metodaservice.isAuthenticated()). jeśli nie, Przekieruj do / login
  • w sekcji logowania, po prostu użyj danych formularza, aby uwierzytelnić użytkownika za pomocą metody service.login()

Dobrym i solidnym przykładem takiego zachowania jest projekt angular-app , a w szczególności jego moduł bezpieczeństwa , który opiera się na niesamowitym Module http Auth Interceptor

Hope this helps

 22
Author: Cétia,
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-03-20 15:53:37

Stworzyłem ten moduł, aby pomóc w tym procesie bułka z masłem

Możesz robić takie rzeczy jak:

$routeProvider
  .state('secret',
    {
      ...
      permissions: {
        only: ['admin', 'god']
      }
    });

Lub też

$routeProvider
  .state('userpanel',
    {
      ...
      permissions: {
        except: ['not-logged-in']
      }
    });

Jest nowy, ale warto sprawdzić!

Https://github.com/Narzerus/angular-permission

 21
Author: Rafael Vidaurre,
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-09-03 05:32:19

Chciałem podzielić się innym rozwiązaniem pracującym z ui router 1.0.0.X

Jak zapewne wiesz, stateChangeStart i stateChangeSuccess są obecnie przestarzałe. https://github.com/angular-ui/ui-router/issues/2655

Zamiast tego powinieneś użyć $transitions http://angular-ui.github.io/ui-router/1.0.0-alpha.1/interfaces/transition.ihookregistry.html

Tak to osiągnąłem:

Najpierw mam i AuthService z kilkoma przydatnymi funkcje

angular.module('myApp')

        .factory('AuthService',
                ['$http', '$cookies', '$rootScope',
                    function ($http, $cookies, $rootScope) {
                        var service = {};

                        // Authenticates throug a rest service
                        service.authenticate = function (username, password, callback) {

                            $http.post('api/login', {username: username, password: password})
                                    .success(function (response) {
                                        callback(response);
                                    });
                        };

                        // Creates a cookie and set the Authorization header
                        service.setCredentials = function (response) {
                            $rootScope.globals = response.token;

                            $http.defaults.headers.common['Authorization'] = 'Bearer ' + response.token;
                            $cookies.put('globals', $rootScope.globals);
                        };

                        // Checks if it's authenticated
                        service.isAuthenticated = function() {
                            return !($cookies.get('globals') === undefined);
                        };

                        // Clear credentials when logout
                        service.clearCredentials = function () {
                            $rootScope.globals = undefined;
                            $cookies.remove('globals');
                            $http.defaults.headers.common.Authorization = 'Bearer ';
                        };

                        return service;
                    }]);

W takim razie mam taką konfigurację:

angular.module('myApp', [
    'ui.router',
    'ngCookies'
])
        .config(['$stateProvider', '$urlRouterProvider',
            function ($stateProvider, $urlRouterProvider) {
                $urlRouterProvider.otherwise('/resumen');
                $stateProvider
                        .state("dashboard", {
                            url: "/dashboard",
                            templateUrl: "partials/dashboard.html",
                            controller: "dashCtrl",
                            data: {
                                authRequired: true
                            }
                        })
                        .state("login", {
                            url: "/login",
                            templateUrl: "partials/login.html",
                            controller: "loginController"
                        })
            }])

        .run(['$rootScope', '$transitions', '$state', '$cookies', '$http', 'AuthService',
            function ($rootScope, $transitions, $state, $cookies, $http, AuthService) {

                // keep user logged in after page refresh
                $rootScope.globals = $cookies.get('globals') || {};
                $http.defaults.headers.common['Authorization'] = 'Bearer ' + $rootScope.globals;

                $transitions.onStart({
                    to: function (state) {
                        return state.data != null && state.data.authRequired === true;
                    }
                }, function () {
                    if (!AuthService.isAuthenticated()) {
                        return $state.target("login");
                    }
                });
            }]);

Widać, że używam

data: {
   authRequired: true
}

Aby oznaczyć stan dostępny tylko wtedy, gdy jest uwierzytelniony.

Następnie, na .Uruchom używam przejść, aby sprawdzić stan autheticated

$transitions.onStart({
    to: function (state) {
        return state.data != null && state.data.authRequired === true;
    }
}, function () {
    if (!AuthService.isAuthenticated()) {
        return $state.target("login");
    }
});

Zbudowałem ten przykład używając kodu znalezionego w dokumentacji $transitions. Jestem całkiem nowy z routerem ui, ale działa.

Mam nadzieję, że może pomóc każdemu.
 16
Author: Sergio Fernandez,
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
2016-09-21 13:12:17

Oto jak wydostaliśmy się z nieskończonej pętli routingu i nadal używaliśmy $state.go zamiast $location.path

if('401' !== toState.name) {
  if (principal.isIdentityResolved()) authorization.authorize();
}
 5
Author: Jason Girdner,
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
2016-06-29 05:49:32

Mam inne rozwiązanie: to rozwiązanie działa idealnie, gdy masz tylko treści, które chcesz pokazać, gdy jesteś zalogowany. Zdefiniuj regułę, w której sprawdzasz, czy jesteś zalogowany, a nie ścieżkę do tras białej listy.

$urlRouterProvider.rule(function ($injector, $location) {
   var UserService = $injector.get('UserService');
   var path = $location.path(), normalized = path.toLowerCase();

   if (!UserService.isLoggedIn() && path.indexOf('login') === -1) {
     $location.path('/login/signin');
   }
});

W moim przykładzie pytam, czy nie jestem zalogowany, a bieżąca trasa, którą chcę wytyczyć, nie jest częścią ` / login', ponieważ Moje trasy do białej listy są następujące

/login/signup // registering new user
/login/signin // login to app
Więc mam natychmiastowy dostęp do tych dwóch tras i każda inna trasa będzie sprawdzana, jeśli są online.

Oto mój cały plik routingu dla modułu logowania

export default (
  $stateProvider,
  $locationProvider,
  $urlRouterProvider
) => {

  $stateProvider.state('login', {
    parent: 'app',
    url: '/login',
    abstract: true,
    template: '<ui-view></ui-view>'
  })

  $stateProvider.state('signin', {
    parent: 'login',
    url: '/signin',
    template: '<login-signin-directive></login-signin-directive>'
  });

  $stateProvider.state('lock', {
    parent: 'login',
    url: '/lock',
    template: '<login-lock-directive></login-lock-directive>'
  });

  $stateProvider.state('signup', {
    parent: 'login',
    url: '/signup',
    template: '<login-signup-directive></login-signup-directive>'
  });

  $urlRouterProvider.rule(function ($injector, $location) {
    var UserService = $injector.get('UserService');
    var path = $location.path();

    if (!UserService.isLoggedIn() && path.indexOf('login') === -1) {
         $location.path('/login/signin');
    }
  });

  $urlRouterProvider.otherwise('/error/not-found');
}

() => { /* code */ } is ES6 syntax, use instead function() { /* code */ }

 3
Author: Chris Incoqnito,
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-27 08:39:44

Use $http Interceptor

Za pomocą $ http interceptor możesz wysyłać nagłówki do Back-endu lub na odwrót i wykonywać swoje kontrole w ten sposób.

Świetny artykuł o $http

Przykład:

$httpProvider.interceptors.push(function ($q) {
        return {
            'response': function (response) {

                // TODO Create check for user authentication. With every request send "headers" or do some other check
                return response;
            },
            'responseError': function (reject) {

                // Forbidden
                if(reject.status == 403) {
                    console.log('This page is forbidden.');
                    window.location = '/';
                // Unauthorized
                } else if(reject.status == 401) {
                    console.log("You're not authorized to view this page.");
                    window.location = '/';
                }

                return $q.reject(reject);
            }
        };
    });
Włóż to do swojego .config or .uruchom funkcję.
 3
Author: TSlegaitis,
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
2017-03-30 10:40:13

Najpierw potrzebujesz usługi, którą możesz wprowadzić do kontrolerów, która ma pewne pojęcie o stanie uwierzytelniania aplikacji. Utrzymywanie szczegółów auth z lokalną pamięcią masową jest przyzwoitym sposobem podejścia do tego.

Następnie musisz sprawdzić stan auth tuż przed zmianą stanu. Ponieważ niektóre strony wymagają uwierzytelnienia, a inne nie, Utwórz trasę nadrzędną sprawdzającą auth i spraw, aby wszystkie inne strony, które tego wymagają, były potomkami tego rodzica.

Wreszcie, będziesz potrzebował sposobu, aby stwierdzić, czy aktualnie zalogowany użytkownik może wykonywać określone operacje. Można to osiągnąć poprzez dodanie funkcji " can " do usługi auth. Może przyjmować dwa parametry: - action-required - (czyli 'manage_dashboard' lub 'create_new_dashboard') - object-opcjonalne-obiekt jest obsługiwany. Na przykład, jeśli masz obiekt Pulpitu nawigacyjnego, możesz sprawdzić, czy pulpit nawigacyjny.ownerId === loggedInUser.id. (oczywiście informacje przekazywane od klienta nigdy nie należy ufać i zawsze należy to zweryfikować na serwerze przed zapisaniem go do bazy danych).

angular.module('myApp', ['ngStorage']).config([
   '$stateProvider',
function(
   $stateProvider
) {
   $stateProvider
     .state('home', {...}) //not authed
     .state('sign-up', {...}) //not authed
     .state('login', {...}) //not authed
     .state('authed', {...}) //authed, make all authed states children
     .state('authed.dashboard', {...})
}])
.service('context', [
   '$localStorage',
function(
   $localStorage
) {
   var _user = $localStorage.get('user');
   return {
      getUser: function() {
         return _user;
      },
      authed: function() {
         return (_user !== null);
      },
      // server should return some kind of token so the app 
      // can continue to load authenticated content without having to
      // re-authenticate each time
      login: function() {
         return $http.post('/login.json').then(function(reply) {
            if (reply.authenticated === true) {
               $localStorage.set(_userKey, reply.user);
            }
         });
      },
      // this request should expire that token, rendering it useless
      // for requests outside of this session
      logout: function() {
         return $http.post('logout.json').then(function(reply) {
            if (reply.authenticated === true) {
               $localStorage.set(_userKey, reply.user);
            }
         });
      },
      can: function(action, object) {
         if (!this.authed()) {
            return false;
         }

         var user = this.getUser();

         if (user && user.type === 'admin') {
             return true;
         }

         switch(action) {
            case 'manage_dashboards':
               return (user.type === 'manager');
         }

         return false;


      }
   }
}])
.controller('AuthCtrl', [
   'context', 
   '$scope', 
function(
   context, 
   $scope
) {
   $scope.$root.$on('$stateChangeStart', function(event, toState, toParams, fromState, fromParams) {
      //only require auth if we're moving to another authed page
      if (toState && toState.name.indexOf('authed') > -1) {
         requireAuth();
      }
   });

   function requireAuth() {
      if (!context.authed()) {
         $state.go('login');
      }
   }
}]

** zastrzeżenie: powyższy kod jest pseudo-kodem i nie ma żadnych gwarancji * *

 2
Author: colefner,
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
2016-05-03 07:05:53