在继续之前,angularjs ui-router授权

amc*_*dnl 3 angularjs angular-ui-router

我有一个angularjs ui-router情况,其中:

  • 在点击任何页面之前,必须先授权用户
  • 如果用户已获得授权且没有路由,请重定向到其主页
  • 如果用户已获得授权并且有路由,则重定向到路由
  • 如果用户已获得授权且没有路由且没有主页,请导航至默认页面
  • 如果用户未经授权且具有路由,则重定向到登录页面,并在授权时重定向到该路由

这是一个棘手的情况,我似乎无法正确指出它.我当前的代码确实可以工作但是......它必须在导航之前显示"登录"页面一瞬间.发生这种情况是因为我不得不以$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');
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

我正在使用一个接受器来处理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');
});
Run Code Online (Sandbox Code Playgroud)

有人有类似的病例,并找到了更好的解决方案吗?

amc*_*dnl 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();
    });

});
Run Code Online (Sandbox Code Playgroud)

基本上,为空路线创建空路线解决了我的问题.有趣.