Angular JS - 防止控制器运行

时间:2014-03-07 20:07:57

标签: angularjs angularjs-routing angularjs-controller

所以我做了一个简单的'是用户登录'检查并将用户重定向到signin.html页面,如果他们没有登录。我的代码看起来像这样:

var myAppModule = angular.module('myApp', ['ngRoute', 'ngCookies']);

myAppModule.config(function($routeProvider) {
$routeProvider
.when('/page2', {
    controller:'pagetwo',
    templateUrl:'pagetwo.html'
})
.when('/signin', {
    controller:'signinCTRL',
    templateUrl:'signin.html'
})

});

myAppModule.run(function($rootScope, userInfo, $location) {
$rootScope.$on('$routeChangeSuccess', function () {
    myCurrentRoute = $location.$$path;

    if(myCurrentRoute != "/signin") {
        userInfo.checkLogin(); //  Check login first. This has the $location.path( "/signin" ); in it.
    }
})

});

我的问题是,当用户转到/ page2时,$ routeChangeSuccess函数会正常触发,并且在userInfo.checkLogin()内部,我将它们重定向到一个新的路由,该路由会在signin.html页面上重定向它们。

问题是 pagetwo控制器在用户重定向到signinCTRL控制器之前仍然会触发

有没有办法阻止pagetwo控制器以某种方式运行?我知道我可能只需将signinCTRL中的所有内容包装起来检查用户是否已登录,但是这样做会使routeChangeSuccess函数。

4 个答案:

答案 0 :(得分:2)

您可以观看$locationChangeStart事件而不是观看$routeChangeSuccess

$locationChangeStart在调用控制器之前被触发。

您可以在how to cancel route navigation in angular

上阅读此博客中有关$locationChangeStart$routeChangeStart之间差异的详情。

demo plunker使用$locationChangeStart

答案 1 :(得分:0)

我已经处理过这个问题,其中登录功能由我的angular js应用程序之外的servlet处理。

我通过javax.servlet.Filter

控制对应用程序的访问

我还有另一个Filter,它用于来自应用程序的所有Json请求。

对于未经身份验证的用户场景,Json过滤器的行为如下;

 httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED); //401

我添加了一个$ rootScope方法,该方法强制登录来自JSON控制器的任何401响应。

   $rootScope.handleHttpFailure = function(data,status) {
        if (401 == status) {
            document.location.reload(true);
        }  else {
            console.log("post ERROR status:" + status + " response:" + data);
            $rootScope.alert('Error received status:'+ status + " response:" + data );
        }
    }

因此,对于您的方案,您无法阻止pagetwo控制器运行,但如果您遵循这种相当简单的模式,则可以阻止它访问安全资源。

答案 2 :(得分:0)

聆听$routeChangeStart而不是$routeChangeSuccess事件可能会在短期内解决您的问题。您还可以在路由resolve地图承诺之一中执行登录检查,并仅针对登录失败返回承诺解除。然后听$ routingChangeError可以导航signin url或者只是从解析promise中导航到它。

对于更完整的rubust路由解决方案,您应该使用ui-router,路由器应该使用任何严重的角度应用程序(并且传闻将来会进入角度核心)。

是的,您应该验证服务器端的正确登录和授权,并在它无效的情况下返回401响应(然后您可以使用精彩的http auth interceptor来处理错误。但是我不同意你应该这样做的想法只有服务器端,这很容易导致用户暴露,你当然应该在客户端进行基本测试

答案 3 :(得分:0)

这是处理错误并且效果很好的最佳方法

function ($routeProvider, $locationProvider, $httpProvider) {
    var interceptor = [
        '$rootScope', '$q', function (scope, $q) {

            function success(response) {
                return response;
            }

            function error(response) {
                var status = response.status;

                if (status == 401) {
                    var deferred = $q.defer();
                    var req = {
                        config: response.config,
                        deferred: deferred
                    };
                    window.location = "/";
                }

                if (status == 404) {
                    var deferred = $q.defer();
                    var req = {
                        config: response.config,
                        deferred: deferred
                    };
                    window.location = "#/404";
                }
                // otherwise
                //return $q.reject(response);
                window.location = "#/500";
            }

            return function (promise) {
                return promise.then(success, error);
            };

        }
    ];
    $httpProvider.responseInterceptors.push(interceptor);
});

// routes
app.config(function($routeProvider, $locationProvider) {
    $routeProvider
        .when('/404', {
            templateUrl: '/app/html/inserts/error404.html',
            controller: 'RouteCtrl'
        })
        .when('/500', {
            templateUrl: '/app/html/inserts/error404.html',
            controller: 'RouteCtrl'
        })

        ......

   };