AngularJS ui-router login authentication

前端 未结 10 2430
[愿得一人]
[愿得一人] 2020-11-22 11:13

I am new to AngularJS, and I am a little confused of how I can use angular-\"ui-router\" in the following scenario:

I am building a web application which consists of

10条回答
  •  清酒与你
    2020-11-22 11:24

    The solutions posted so far are needlessly complicated, in my opinion. There's a simpler way. The documentation of ui-router says listen to $locationChangeSuccess and use $urlRouter.sync() to check a state transition, halt it, or resume it. But even that actually doesn't work.

    However, here are two simple alternatives. Pick one:

    Solution 1: listening on $locationChangeSuccess

    You can listen to $locationChangeSuccess and you can perform some logic, even asynchronous logic there. Based on that logic, you can let the function return undefined, which will cause the state transition to continue as normal, or you can do $state.go('logInPage'), if the user needs to be authenticated. Here's an example:

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

    Keep in mind that this doesn't actually prevent the target state from loading, but it does redirect to the log-in page if the user is unauthorized. That's okay since real protection is on the server, anyway.

    Solution 2: using state resolve

    In this solution, you use ui-router resolve feature.

    You basically reject the promise in resolve if the user is not authenticated and then redirect them to the log-in page.

    Here's how it goes:

    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()
          }
        }
      }
    )
    

    Unlike the first solution, this solution actually prevents the target state from loading.

提交回复
热议问题