Перенаправление страницы с угловой маршрутизацией после успешного вызова API на экспресс-сервере

В одностраничном приложении, использующем угловую маршрутизацию, как я могу перенаправить страницу после вызова API. В моем случае я хочу перенаправить пользователя на страницу профиля после того, как он вызвал API входа в систему. Так что я думал, что это сработает, но это не так.

На клиенте main.js. У меня настроена угловая маршрутизация

app.config(function($routeProvider){   $routeProvider
//the home page display
.when('/', {
  templateUrl: 'main.html',
  controller: 'mainController'
})

.when('/login', {
  templateUrl: 'login.html',
  controller: 'loginController'
})

.when('/signUp', {
  templateUrl: 'signUp.html',
  controller: 'signUpController'
})

.when('/profile', {
  templateUrl: 'profile.html',
  //controller: 'mainController'
}); });

и с моего контроллера я вызываю / логин пост API

app.controller('authController', function($scope, $http, $rootScope, $location){   
  $scope.user = {username: '', password: ''};   
  $scope.error_message = '';

  $scope.login = function(){
    $http.post('/login', $scope.user).success(function(data){
      if(data.state == 'success'){
        //set username authenticated property to true after successful log in
        //I am only pasting some of my code here, more logic before controller
        $rootScope.authenticated = true;
        $rootScope.current_user = "james";
        $location.path('/profile');
      }
      else{
        $scope.error_message = data.message;
      }
    });   
  }; 
});

и вот мой логин API

router.post('/login', passport.authenticate('local-login', {
        successRedirect : '/success', // redirect to the secure profile section
        failureRedirect : '/failure', // redirect back to the signup page if there is an error
        failureFlash : true // allow flash messages
    }));

и когда это успешно, это вызывает успех, который возвращает данные, которые должны вызвать обратный вызов в $http.post и перенаправить страницу через $location.path('/profile');. Однако обратный вызов не вызывается, и на моей странице отображается информация о пользователе из res.send.

//sends successful login state back to angular
    router.get('/success', function(req, res){
        res.send({state: 'success', user: req.user ? req.user : null});
    });

Я на правильном пути? Я просто следую учебному пособию Майкрософт https://www.microsoftvirtualacademy.com/en-us/training-courses/mean-stack-jump-start-8442 но их заполненная страница на github даже не работает, поэтому не помогает я отлаживаю эту мою проблему.

3 ответа

Решение

С помощью successRedirect а также failureRedirect в паспорте перенаправит клиента на указанные страницы, что предотвратит вашу маршрутизацию angularJS на стороне клиента. Причина, по которой вы видите информацию о пользователе после входа в систему, заключается в том, что ваш клиент перенаправляется на /success страницы, а не фактически отвечая на первоначальный запрос. Затем клиент извлекает страницу успеха с помощью запроса GET, и на новый запрос GET затем отправляется информация о пользователе.

Я бы предложил оставить перенаправления node.js при использовании AngularJS, так как вы, вероятно, захотите обработать перенаправление на стороне клиента:

router.post('/login', passport.authenticate('local-login'), function(req, res){
    res.send(req.user);
});

Встроенная функция никогда не будет выполняться, если пользователь не аутентифицирован. Вместо этого, паспорт ответит напрямую с ошибкой 401, с телом "Unauthorized". Следовательно success состояние не требуется. На стороне клиента вы должны использовать .error() функция для устранения ошибок 401 вместо проверки вашей переменной состояния:

$http.post('/login', $scope.user).success(function(user){
    $rootScope.authenticated = true;
    $rootScope.current_user = "james";
    $location.path('/profile');
  })
 .error(function(err){
    $scope.error_message = err;
  });

Если вы хотите передать более конкретную причину того, почему запрос был неавторизованным (что не всегда является хорошей идеей), вы можете использовать флэш-сообщения и выполнить другой запрос GET от angular, чтобы получить более подробное сообщение об ошибке авторизации.

Похоже, у вас небольшое несоответствие импеданса в том, что интерфейс и сервер хотят здесь сделать. В вашем коде AngularJS предполагается сделать POST для конечной точки API и получить 200 (успех) вместе с некоторыми данными JSON, которые сообщают ему об успехе или неудаче попытки входа в систему.

Серверная часть думает, что получит POST, а затем перенаправит абонента в новое место. По крайней мере, так я это читаю. Это не просто отправка некоторых данных с HTTP-кодом ответа 200 или кодом ошибки.

Я думаю, что вы хотите настроить внутренний код, чтобы просто возвращать данные во внешний интерфейс, чтобы получить ожидаемый результат.

До сих пор я не видел успеха в том, чтобы Ajax обращался к API, перенаправляя на страницу. У нас похожая ситуация, когда вызов API может привести к перенаправлению на страницу ошибки. Мы хотели обработать это на сервере, а не запрашивать пользовательский интерфейс (Angular). Но просто печально видеть, что ни один из методов перенаправления, таких как res.redirect, не работает. Наш сценарий заключается в том, что Angular делает вызов API через Ajax, и API, работающий на Node.js, должен перенаправлять на html-страницу.

Другие вопросы по тегам