angularjs重定向到登录页面,如果未进行身份验证,则出现异常

angularjs重定向到登录页面,如果未进行身份验证,则出现异常,angularjs,authentication,redirect,routing,Angularjs,Authentication,Redirect,Routing,编辑:忘了提到我和AngularJs只合作了一周,所以如果你看到一些你认为应该改进的东西,并且与问题本身无关,请在评论部分告诉我 好的,我有我的身份验证控制器和提供者,我不会展示它们,因为它们与问题的范围无关。 然后我有一个拦截器来检查用户在调用时是否经过身份验证。如果是这样,我在请求上设置身份验证头以包含用户的令牌,如果不是这样,我将用户重定向到登录页面,甚至不向服务器发出请求(显然,如果有人绕过此设置,API上还有一个授权) 我想添加一些例外,这意味着即使用户没有身份验证令牌,我也希望允许

编辑:忘了提到我和AngularJs只合作了一周,所以如果你看到一些你认为应该改进的东西,并且与问题本身无关,请在评论部分告诉我


好的,我有我的身份验证控制器和提供者,我不会展示它们,因为它们与问题的范围无关。 然后我有一个拦截器来检查用户在调用时是否经过身份验证。如果是这样,我在请求上设置
身份验证
头以包含用户的令牌,如果不是这样,我将用户重定向到登录页面,甚至不向服务器发出请求(显然,如果有人绕过此设置,API上还有一个
授权

我想添加一些例外,这意味着即使用户没有身份验证令牌,我也希望允许一些页面。如果这是一个特定的路径,我可以这样做,但我想允许访问我的404页面,并且它位于我指定的
路由中
。否则
要转到404页面,我如何使我的拦截器仅在不转到该页面时重定向到登录

拦截器

.factory('authInterceptorService', ['$q', '$location', 'localStorageService', function ($q, $location, localStorageService) {

    var authInterceptorServiceFactory = {};

    var authData = localStorageService.get('authorizationData');

    var _request = function (config) {

        config.headers = config.headers || {};

        if (authData) {
            config.headers.Authorization = 'Bearer ' + authData.token;
        } else if ($location.path != '/accounts/login' && $location.path != '/accounts/register') {
            $location.path('/accounts/login');
        }

        return config;
    }

    var _responseError = function (rejection) {
        if (rejection.status === 401) {
            $location.path('/accounts/login');
        }
        return $q.reject(rejection);
    }

    authInterceptorServiceFactory.request = _request;
    authInterceptorServiceFactory.responseError = _responseError;

    return authInterceptorServiceFactory;
}])
在我的行程中

 $urlRouterProvider.otherwise('/page-not-found');

 $stateProvider
     (...)//rest of the states

     .state('page-not-found', {
         url: '/page-not-found',
         templateUrl: '/Content/partials/error/404.html',
         data: {
             displayName: false
         }
     })

     (...)//rest of the states
我尝试将
“/page not found”
添加到我的
if
中,但它无法按预期工作,因为在第一次检查位置时,它仍然没有重定向

编辑 正如charlietfl所建议的,我现在尝试使用resolve,但它甚至没有传递我的函数

我从拦截器中删除了以下代码:

else if ($location.path != '/accounts/login' && $location.path != '/accounts/register') {
    $location.path('/accounts/login');
}
并向身份验证模块添加新的
服务

.service('authCheckService', ['$http', '$q', 'localStorageService', function ($http, $q, localStorageService) {
    var self = {
        'onlyLoggedIn': function ($state, $q) {
            var deferred = $q.defer();
            var authData = localStorageService.get('authorizationData');
            console.log(authData);
            if (authData) {
                deferred.resolve();
            } else {
                deferred.reject();
                $state.go('login');
            }
            return deferred.promise;
        }
    }

    return self;
}]);
我试着称之为:

.state('smo-dashboard', {
        url: '/dashboard',
        templateUrl: '/Content/partials/dashboard.html',
        resolve: authCheckServiceProvider.onlyLoggedIn
})

请注意,我正在尝试记录authData
var
,以检查它是否正常工作,但它没有工作,并且控制台上也没有错误。

类似的错误服务可以帮助根据响应中的状态处理要做的事情:

"严格使用",

/**
 * Error Service
 */

angular.module('app.errorService', [])
        .factory("errorService", function ($route, $location) {        
                return {   
                    checkAndReturnError: function(a,b,c) {
                        if (a.status === 401){
                            (function(){
                                return $location.path("/accounts/login");
                            }());
                            return;
                        }
                        if (a.status === 404)
                            return;

                           alert("Error \n *" + a.data.message);

                    }
                };
        });
然后,当你打电话时,如果响应状态为401,它将重定向。vbad的问题是,您必须将其添加到所有调用中:

            $scope.pageChanged = function() {
                $scope.Promise = Resource.get({}, function(response) {
                }, errorService.checkAndReturnError);
            };

最终找到了如何使用resolve解决它

首先,我完全删除了我以前使用的拦截器。 然后,我在路由
.config
中创建了一个函数,用于身份验证的每个
解析。最后,为了处理我的
解析
,我使用
$stateChangeError
重定向到登录
状态

路由配置

.config(function ($stateProvider, $urlRouterProvider) {

    // function to check the authentication //
    var Auth = ["$q", "authService", function ($q, authService) {
        authService.fillAuthData;
        if (authService.authentication.isAuth) {
            return $q.when(authService.authentication);
        } else {
            return $q.reject({ authenticated: false });
        }
    }];

    /* if the state does not exist */
    $urlRouterProvider
        .otherwise('/page-not-found'); 

    $stateProvider

        // state that allows non authenticated users //
        .state('home', {
            url: '/',
            templateUrl: '/Content/partials/home.html',
        })

        // state that needs authentication //
        .state('smo-dashboard', {
            url: '/dashboard',
            templateUrl: '/Content/partials/dashboard.html',
            resolve: {
                auth: Auth
            }
        })

        // errors //
         .state('page-not-found', {
             url: '/page-not-found',
             templateUrl: '/Content/partials/error/404.html'
         })

        // accounts //
        .state('login', {
            url: '/accounts/login',
            templateUrl: '/Content/partials/account/login.html'
        })

        // OTHER STATES //
    }
);
在主控制器中

$scope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) {
    $state.go("login");
});

一个建议是为所有需要登录的路径设置一个父状态。然后,您可以在该父级上有一个
解析
,如果用户未登录,则该状态的所有子级都无法访问,因为父级无法解析。对于所有其他路线,都不会有任何问题check@charlietfl尝试按建议使用
解决
,但我可能做错了什么,请看一下我的编辑。只想添加一些关于real app问题的文字,我正在将用户重定向到登录页面,如果我拒绝承诺,在浏览器上实际发生重定向之前,会有大量未经授权的请求发送到服务器。所以我决定在重定向之前不拒绝错误。我想要的是对某些页面有一个401状态响应,即使没有对服务器的调用。这意味着我有一个仪表板页面,它只是一个部分视图,没有对API本身的调用,我想将其限制为经过身份验证的用户