2014-06-23 92 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