未登录时阻止访问视图

时间:2017-03-21 21:39:54

标签: javascript angularjs express mean-stack

目标:

仅允许已登录的用户访问个人资料页面。登录系统使用mongodb和passport-local。

当前代码:

我有以下快递路线,我用它来检查请求是否经过身份验证。

app.get('/loggedin', function(req, res) { 
    res.send(req.isAuthenticated() ? req.user : '0'); 
});

然后我使用服务通过$http呼叫路由并返回。我将此服务命名为AuthService

this.isLoggedIn = function(){
    var promise = $http.get('/loggedin');

    promise.then(function(user){
        if(user === 0 || user === '0'){
            //Not a valid request
            console.log('Not a valid request');
            return false
        } else {
            //Valid request.
            return user
        }
    });

    return promise;
};

当解析promise返回false时,应该通过抛出错误来处理路由的代码。

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/profile', {
    templateUrl: 'views/profile.html',
    controller: 'profileCtrl',
    resolve: {
      loggedIn: ['AuthService', function(AuthService){
        return AuthService.isLoggedIn()
      }]
    }

  });
}])

用于处理上述代码应该抛出的错误的代码。

.run(['$rootScope','$location', function($rootScope,$location){

  //Error thrown by a resolve dependency. Handle the error here.
  $rootScope.$on('$routeChangeError', function(event, curRoute, prevRoute, error){
    console.log("Routing error");
  }); 

}])

问题:

当前问题是Routing error消息未记录到控制台。 (上面的代码)。该服务正在将Not a valid request记录到控制台,所以我知道到目前为止所做的一切都正常,但我不确定为什么这不会导致$ routeChangeError。一旦我可以获得此日志记录,我就可以通过重复resolve逻辑来锁定我想要的任何页面,这是所有这一切的最终目标。

2 个答案:

答案 0 :(得分:1)

从承诺中返回false并不会使其拒绝。因此,对于所有意图和目的,路由器认为resolve成功。你需要拒绝你的承诺,你可以通过抛出错误而不是返回false来做到这一点:

this.isLoggedIn = function(){
    var promise = $http.get('/loggedin');

    promise.then(function(user){
        if(user === 0 || user === '0'){
            //Not a valid request
            console.log('Not a valid request');
            throw new Error('Not a valid request');
        } else {
            //Valid request.
            return user
        }
    });

    return promise;
};

谨防。你无法真正锁定浏览器中的任何内容。你将实现的最好的目标是“美化”隐藏页面。用户将始终能够使用JavaScript直接操作浏览器。因此,不要直接在这些页面上放置任何敏感内容,并且您需要确保这些页面检索的任何数据,只有在用户登录时才能检索。

更新

使用promises而不是抛出异常的解决方案的略短版本。

this.isLoggedIn = function(){
    return $http.get('/loggedin').then(function(user){
        if(user === 0 || user === '0'){
            //Not a valid request
            console.log('Not a valid request');
            return $q.reject('Not a valid request');
        }
        return $q.resolve(user);
    });
};

答案 1 :(得分:1)

你的代码看起来都很不错,你在这里肯定有正确的想法。唯一的问题是$ routeChangeError认为一切正常,它应该根据你的代码。您需要实际拒绝承诺,以便路由库意识到发生了一些不好的事情。

尝试使用promise(使用AngularJS' $ q库)包装$ http调用,然后在响应不符合预期时拒绝承诺:

this.isLoggedIn = function() {
        var deferred = $q.defer();
        var promise = $http.get('/loggedin');
        promise.then(function(user) {
            if(user === 0 || user === '0'){ 
                 deferred.reject(user);
            }
            deferred.resolve(data);
        },
        function(error) {
            deferred.reject(error);
        });

        return deferred.promise;
}

或者,您可以简单地抛出错误,而不是拒绝承诺。