MEAN使用passport-local和$ routeProvider堆栈用户身份验证

时间:2017-03-20 23:03:58

标签: javascript angularjs express passport.js mean-stack

我使用本地护照将用户登录到我的应用程序中。我们通过以下在angularJS控制器中调用的函数登录。

$http.post('/login', $scope.user).then(function (response){
    if(response.data.success){
        //If successful I console.log the user data and redirect them to the main page.
        console.log(response.data.user);
        $location.path(response.data.redirectTo);
    } else {
        // Handle the error messages passed back by my express routing.
    }
});

这是按预期工作的,如果我使用正确的详细信息登录,那么它将console.log用户,然后将我重定向到新页面。

我的问题是我现在如何制作它所以我的所有其他页面都会确保用户已登录?我应该使用我收到的用户数据? 我正在谈论的页面使用下面的$ routeProvider路由:

app.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/login', {
    templateUrl: 'login.html',
    controller: 'loginCtrl'
  });

  $routeProvider.when('/home', {
    templateUrl: 'home.html',
    controller: 'homeCtrl',
    // Something to make sure the user is logged in
  });

}])

我读过的所有教程都要求我通过快速路由处理这个问题,但这只会导致重定向循环,因为/login没有通过isAuthenticated路由中间件。

app.get('*', isAuthenticated, function(req,res){
    res.sendFile("index.html");
});

function isAuthenticated(req,res,next){
    if(req.isAuthenticated()){
        next();
    } else {
        res.redirect('/login');
    }
}

如何从这里向前迈进的任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:1)

您的angularJs应用程序需要检测何时需要登录。为此,您需要为从Express应用程序获得的所有响应编写拦截器,如果需要登录,请显示登录页面。在最好的世界中,您的快递应用程序不应该重定向到/ login,您应该将路由保留到angularJs应用程序;它应该只发送json资源或诸如401状态代码响应之类的东西来表明该请求是未经授权的。

收到未经授权的标题后,您的angularJs拦截器将看到需要登录并显示登录页面:

app.config(function($httpProvider) {

    //configure $http to show a login dialog whenever a 401 unauthorized response arrives
    $httpProvider.responseInterceptors.push(
            function($rootScope, $q, $location) {

                return function(promise) {
                    return promise.then(
                            //success -> don't intercept            
                            function(response) {
                                return response;
                            },
                            //error -> if 401 save the request and broadcast an event
                                    function(response) {
                                if (response.status === 403 || response.status === 401) {
                                            var deferred = $q.defer(),
                                                    req = {
                                                        path: $location.path(),
                                                        config: response.config,
                                                        deferred: deferred
                                                    };
                                            $rootScope.requests401.push(req);
                                            $rootScope.$broadcast('event:loginRequired');
                                            return deferred.promise;
                                        }
                                        return $q.reject(response);
                                    }
                            );
                        };
            });
         });            
app.run(function($rootScope, $http, $location, base64) {


/**
 * Holds all the requests which failed due to 401 response.
 */
$rootScope.requests401 = [];

$rootScope.$on('event:loginRequired', function() {
    $location.path('/login');
});

/**
 * On 'event:loginConfirmed', resend all the 401 requests.
 */
$rootScope.$on('event:loginConfirmed', function(){

    var i, requests = $rootScope.requests401,
            retry = function(req) {
                $http(req.config).then(function(response) {
                    req.deferred.resolve(response);
                });
            };

        });
});

在此设置中,您的LoginCtrl还需要发出loginConfirmed事件。从登录中获得用户后,您可以将详细信息存储在根作用域中,以便以后访问。