AngularJS UI-Router。如何重定向到登录页面。

55

我有4个状态:dashboarddahboard.maindashboard.minorlogin。 dashboard是抽象的,并且它是.minor和.main状态的父状态。 以下是我的代码:

.state('dashboard', {
        url: "/dashboard",
        abstract: true,
        templateUrl: "views/dashboard.html",
        resolve: {
            auth: function ($q, authenticationSvc) {
                var userInfo = authenticationSvc.getUserInfo();
                if (userInfo) {
                    return $q.when(userInfo);
                } else {
                    return $q.reject({ authenticated: false });
                }
            }
        },
        controller: "DashboardCtrl",
        data: { pageTitle: 'Example view' }
    })
    .state('dashboard.main', {
        url: "",
        templateUrl: "views/main.html",
        controller: "DashboardCtrl",
        data: { pageTitle: 'Main view' }
    })

正如您在仪表板状态中看到的那样,我有解决方案。通过这个解决方案,如果用户未经授权,我希望将其重定向到登录页面。出于这个原因,我使用特殊的authenticationSvc服务:

.factory("authenticationSvc", ["$http", "$q", "$window", function ($http, $q, $window) {
    var userInfo;

    function login(email, password) {
        var deferred = $q.defer();

        $http.post("/api/login", { email: email, password: password })
            .then(function (result) {
                if(result.data.error == 0) {
                    userInfo = {
                        accessToken: result.data.accessToken
                    };
                    $window.sessionStorage["userInfo"] = JSON.stringify(userInfo);
                    deferred.resolve(userInfo);
                }
                else {
                    deferred.reject(error);
                }
            }, function (error) {
                deferred.reject(error);
            });

        return deferred.promise;
    }
    function getUserInfo() {
        return userInfo;
    }
    return {
        login: login,
        logout: logout,
        getUserInfo: getUserInfo
    };
}]);

我在配置文件中检查认证值:

.run(function($rootScope, $location, $state) {
    $rootScope.$state = $state;
    $rootScope.$on("routeChangeSuccess", function(userInfo) {
        consol.log(userInfo);
    });
    $rootScope.$on("routeChangeError", function(event, current, previous, eventObj) {
        if(eventObj.authenticated === false) {
            $state.go('login');
        }
    });
});

但是不幸的是,当我进入我的网站根目录或仪表板状态时,我得到了一个空白页面。这段代码有什么问题吗?谢谢!


1
事件名称实际上是$routeChangeSuccess$routeChangeError(请注意前面的$)...难道不可能简单些吗? - Clive
3个回答

77

重点是,如果已经重定向到预期状态,则不要再进行重定向。这里有一个类似解决方案的可工作的plunker

.run(function($rootScope, $location, $state, authenticationSvc) {


    $rootScope.$on( '$stateChangeStart', function(e, toState  , toParams
                                                   , fromState, fromParams) {

        var isLogin = toState.name === "login";
        if(isLogin){
           return; // no need to redirect 
        }

        // now, redirect only not authenticated

        var userInfo = authenticationSvc.getUserInfo();

        if(userInfo.authenticated === false) {
            e.preventDefault(); // stop current execution
            $state.go('login'); // go to login
        }
    });
});

请查看以下类似的解释:


提示他人:这个优秀答案中的代码就是你需要的。参考的 Plunkr 很好,但过于冗长。 - rinogo
此示例仅适用于旧版本(0.2)。对于更新的版本(1.x),请阅读此迁移指南:https://ui-router.github.io/guide/ng1/migrate-to-1_0#state-change-events - terox

4

由于您正在使用UI-Router模块,因此您应该使用$stateChangeStart$stateChangeSuccess事件。

请查阅以下链接获取更多信息:https://github.com/angular-ui/ui-router/issues/17

console中的consol.log(userInfo)存在一个拼写错误。

检查您的Chrome开发工具中的控制台,它会提示是否还有其他遗漏的东西。


谢谢!现在,当我未经授权地访问我的网站根目录时,我被重定向到登录页面,但是当我进入仪表板状态时,我只看到一个空白页面。 - Yelnar
你有检查浏览器控制台的输出吗? - Vamshi Suram
1
今天我遇到了同样的情况,我的仪表板状态有一个 resolve:;然而,在我的 app.js 监听器 ($rootScope.$on('$stateChangeStart') 中,它卡在了 event.preventDefault();。我得到了 Angular 无限循环错误。为什么会这样? - bob.mazzo

0
请注意,实际上$stateChangeSuccess事件已被弃用,并且在angular-ui-route包中不再可用。现在,这个行为由转换钩子处理。您可以使用$transitions.onStart来实现您的目的,如下所示:
run.$inject = ['$transitions', 'authenticationSvc'];
function run($transitions, authenticationSvc) {

  $transitions.onStart({}, function (trans) {
    var userInfo = authenticationSvc.getUserInfo();

    var $state = trans.router.stateService;

    if(userInfo.authenticated === false) {
        $state.go('login'); // go to login
    }
  });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接