2014-06-23 181 views
3

之前,我有其中一個angularjs UI路由器的情況:angularjs UI路由器授權繼續

  • 用戶必須擊中任何頁面
  • 如果用戶被授權,也沒有途徑之前被授權,重定向到他們的主頁
  • 如果用戶被授權並且都有一個路由,重定向路由
  • 如果用戶被授權,也沒有路線,沒有主頁,瀏覽到默認頁面
  • 如果用戶沒有被授權並有路線,重定向登錄頁面和授權重定向到該路線

它的一個棘手的情況,我似乎無法指出它恰到好處。我目前的代碼確實有效,但是......它必須在導航前的一秒鐘內顯示「登錄」頁面。發生這種情況是因爲我必須以某種方式啓動$stateChangeStart

var app = angular.module('myapp', ['ui.router']); 

// handle default states based on authentication, 
// default properties set in user profile, or 
// or just redirect to 'apps' page 
var authd = false, 
    defaultDashboard = undefined, 
    defaultFn = function($injector){ 
     // required to get location since loaded before app 
     var $location = $injector.get('$location'); 

     // if the user has a default dashboard, navigate to that 
     if(defaultDashboard){ 
      $location.path('workspace/' + defaultDashboard); 
     } else if(authd) { 
      // if the user is auth'd but doesn't have url 
      $location.path('home'); 
     } else { 
      // if we aren't auth'd yet 
      $location.path('login'); 
     } 
    }; 

app.config(function ($urlRouterProvider, $locationProvider, $stateProvider) { 
    $locationProvider.html5Mode(true); 
    app.stateProvider = $stateProvider; 

    $urlRouterProvider.otherwise(function($injector){ 
     defaultFn($injector); 
    }); 
}); 

app.run(function ($rootScope, $q, $location, $state, $stateParams, $injector, security) { 

    var deregister = $rootScope.$on("$stateChangeStart", function() { 

     // authorize is a AJAX request to pass session token and return profile for user 
     security.authorize().success(function(d){ 

      // set some local flags for defaultFn 
      authd = true; 
      defaultDashboard = d.defaultDashboard; 

      // de-register the start event after login to prevent further calls 
      deregister(); 

      // switch to default view after login 
      if($location.$$url === "/login" || 
        $location.$$url === "/"){ 
       defaultFn($injector); 
      } 

     }).error(function(){ 
      $location.path('login'); 
     }); 
    }); 
}); 

我使用一個攔截器來處理像401S:

var module = angular.module('security.interceptor', []); 

// This http interceptor listens for authentication failures 
module.factory('securityInterceptor', function($injector, $location) { 
    return function(promise) { 

     // Intercept failed requests 
     return promise.then(null, function(originalResponse) { 
      if(originalResponse.status === 401) { 
       $location.path('/login'); 
      } 

      return promise; 
     }); 
    }; 
}); 

// We have to add the interceptor to the queue as a string because the 
// interceptor depends upon service instances that are not available in the config block. 
module.config(function($httpProvider) { 
    $httpProvider.defaults.withCredentials = true; 
    $httpProvider.responseInterceptors.push('securityInterceptor'); 
}); 

人有任何類似的情況,並找到了一個更好的解決方案?

+0

我不確定這是一個非常好的解決方案,可以在.run函數中進行重新路由。爲什麼你先設置$ location.path,然後等待.run來啓動它?爲什麼不使用$ state.go()? http://angular-ui.github.io/ui-router/site/#/api/ui.router.state.$state。最後,你如何以及在哪裏存儲會話數據?本地存儲?還有別的嗎? –

+0

@Bonatoc - 它的服務器請求,它的用戶配置文件。關於跑步,你能否提供一些細節? – amcdnl

+0

你有沒有把本教程作爲你劇本的基礎? http://arthur.gonigberg.com/2013/06/29/angularjs-role-based-auth/。是的,我的不好,.run顯然是執行auth檢查的地方,因爲它是在.config之後被解僱的。 –

回答

5

繼承人我的解決方案,我想出了:

app.config(function ($urlRouterProvider, $locationProvider, $stateProvider) { 
    $locationProvider.html5Mode(true); 

    // placeholder 
    $stateProvider.state('welcome', { 
     url: '/' 
    }); 

    $urlRouterProvider.otherwise('404'); 
}); 

app.run(function ($rootScope, $q, $location, $state, $stateParams, security, $urlRouter) { 

    var deregister = $rootScope.$on("$stateChangeStart", function (event) { 
     // stop the change! 
     event.preventDefault(); 

     security.authorize().success(function(d){ 
      // if we don't have a previous url 
      if($location.$$url === "/" || $location.$$url === "/login"){ 

       // If user has a preset home 
       if(d.defaultDashboard){ 
        $location.path('workspace/' + d.defaultDashboard); 
       } else { 
        $location.path('welcome'); 
       } 
      } else { 
       // if we do, then continue 
       $urlRouter.sync(); 
      } 
     }).error(function(){ 
      // redirect to home 
      $location.path('login'); 
     }); 

     // deregister the listener 
     deregister(); 
    }); 

}); 

實質上,空航線創建一個空的路線解決我的問題。有趣。

+0

聽起來有點狡猾,但它的作品正確! – iamryandrake