继续之前,angularjs ui路由器授权

继续之前,angularjs ui路由器授权,angularjs,angular-ui-router,Angularjs,Angular Ui Router,我有一个angularjs ui路由器的情况,其中: 用户必须在点击任何页面之前获得授权 如果用户已授权且没有路由,请重定向到其主页 如果用户已授权并拥有路由,则重定向到路由 如果用户已授权且没有路线和主页,请导航到默认页面 若用户未经授权且有路由,则重定向至登录页面,并在授权后重定向至该路由 这是一个棘手的情况,我似乎不能正确地处理它。我当前的代码确实有效,但是。。。在导航之前,它必须在一瞬间显示“登录”页面。发生这种情况是因为我必须以某种方式启动$stateChangeStart var

我有一个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');
        });
    });
});
我用一个接收器来处理401,比如:

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

有人遇到过类似的情况并找到了更好的解决方案吗?

这是我提出的解决方案:

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函数中是否是一个很好的解决方案。为什么要先设置$location.path,然后再等待.run启动它?为什么不使用$state.go()。最后,如何以及在何处存储会话数据?本地存储?还有别的吗?@Bonatoc-它是一个服务器请求,它是一个用户配置文件。关于跑步,你能提供更多的细节吗?你有没有把本教程作为你的脚本的基础。是的,我的坏,.run显然是执行身份验证检查的地方,因为它是在.config之后触发的。@bonatocya类似的,我添加了我使用的接收器