如何检查身份验证并使用ui-router自动重定向到登录状态?

ymg*_*ymg 3 angularjs angularjs-service angularjs-routing

所以我run在angularjs中有这个功能(运行AngularJS v1.2.26)

.run(function(....) {
    authService.authCheck();

    $rootScope.$on('$routeChangeStart', function(event, next, current) {
        if (next.requireLogin) {
            if (!authService.isLoggedIn()) {
                $location.path('/login');
                event.preventDefault();
            }
        }
    });

})...
Run Code Online (Sandbox Code Playgroud)

当直接访问需要身份验证的URL时,例如http://127.0.0.1:8080/secret,该函数总是重定向到登录路径,在调试它一段时间后,它会一直评估为false.访问默认页面然后转到指定的路由它运行没有任何问题.

这是我的一部分 authService

this.authCheck = function() {
    $http({
        method: 'PUT',
        url: '/api/login'
    }).
    success(function(data, status, headers, config) {
        if (status === 200) {
            userIsAuthenticated = true;
        } else {
            userIsAuthenticated = false;
        }
        $rootScope.loginStatus = userIsAuthenticated;
    }).
    error(function(data, status, headers, config) {
        userIsAuthenticated = false;
        $rootScope.loginStatus = userIsAuthenticated;
    });
};

this.isLoggedIn = function() {
    return userIsAuthenticated;
};
Run Code Online (Sandbox Code Playgroud)

因此,每当我有一个断点时,!authService.isLoggedIn()即使运行块中的$rootScope.$on函数在到达函数之前尝试对其进行身份验证,我也会看到它的计算结果为false .

究竟什么阻止userIsAuthenticated变量状态持久?

hon*_*n2a 6

.authCheck你的authService是异步的,这意味着userIsAuthenticated,直到它实际上完成首次将不会被设置为true.如果您按照现在的路线进行操作,则必须编写一些更复杂的代码,以便等待检查尚未完成然后重定向.然而,这是一个混乱的次优选择.

到这里的最佳方式是让ui-router你为此工作.为需要登录的所有州创建共同的祖先状态,例如'session'.然后使用该resolve选项使该状态的解决方案等待您的身份验证检查.如果未经过身份验证,请创建特定的状态传输拒绝错误,您可以在其他地方捕获并执行操作(重定向到登录).

.state('session', {
    resolve: {
        authentication: ['authService', '$q', function (authService, $q) {
            return authService.checkAuthentication().then(function () {
                if (!authService.isAuthenticated) {
                    return $q.reject({
                        notAuthenticated: true
                    });
                }
            });
        }]
    },
    // ...
})
.state('secret', {
    parent: 'session',
    // ...
});
Run Code Online (Sandbox Code Playgroud)

然后

$rootScope.$on('$stateChangeError', function (_0, _1, _2, _3, _4, error) {
    if (error.notAuthenticated) {
        $state.go('login');
    }
});
Run Code Online (Sandbox Code Playgroud)

(您还需要从身份验证检查中正确返回)

checkAuthentication: function () {
    return $http({...})
        .success(...)
        .error(...);
}
Run Code Online (Sandbox Code Playgroud)