How to check authentication and automatically redirect to login state with ui-router?

萝らか妹 提交于 2019-12-06 09:35:34

问题


so I have this function in my run in angularjs (running 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();
            }
        }
    });

})...

when directly accessing a URL that requires authentication e.g. http://127.0.0.1:8080/secret, the function always redirects to the login path, clearly after debugging it for a while it evaluates to false all the time. when accessing default page then going to the specified route it runs without any problems.

This is part of my 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;
};

So every time I have a break point on !authService.isLoggedIn() I see that it evaluates to false even though the function in the run block tries to authenticate it before reaching the $rootScope.$on function.

What exactly is preventing the state of userIsAuthenticated variable from being persistent?


回答1:


The .authCheck in your authService is asynchronous, which means that userIsAuthenticated won't be set to true until it actually finishes for the first time. If you followed the route you're on now, you'd have to write some more complex code for waiting if the check isn't completed yet and then redirecting. However, that's a messy sub-optimal option.

The best way to go here is to let ui-router work this out for you. Create a common ancestor state for all your states that require login, e.g. 'session'. Then make that state's resolution wait for your authentication check using resolve option. If not authenticated, create a specific state transfer rejection error, which you can elsewhere catch and act upon (redirect to login).

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

and then

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

(you'll need to properly return from your authentication check as well)

checkAuthentication: function () {
    return $http({...})
        .success(...)
        .error(...);
}



回答2:


Did you allow the application to send request from /secret ? It may prevent you to send any request from there so it redirects you to login



来源:https://stackoverflow.com/questions/27065317/how-to-check-authentication-and-automatically-redirect-to-login-state-with-ui-ro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!