Подтвердить что ты не робот

AngularJS - проверка подлинности пользователя, а затем маршрутизация на правильную страницу

Что я хочу делать, когда пользователь приходит на страницу index.html Мне нужен модуль входа в систему, чтобы сделать 2 вещи:

  • Мне нужно это, чтобы проверить, прошел ли аутентификация пользователя (что, я думаю, я уже начал с "function authService" ), если у пользователя есть действительный токен, затем измените ui-view на dashboard/dashboard.html и если ключ недействителен или вообще нет ключа, загрузите login/login.html в ui-view.

  • Как только они успешно вошли в систему, я хочу, чтобы они были перенаправлены на "dashboard/dashboard.html"

Вот мой логин script:

function authInterceptor(API) {
  return {
    request: function(config) {
      if(config.url.indexOf(API) === 0) {
        request.headers = request.headers || {};
        request.headers['X-PCC-API-TOKEN'] = localStorage.getItem('token');
      }
      return config;
    }
  } 
}

function authService(auth) {
  var self = this;
  self.isAuthed = function() {
    localStorage.getItem('token');
  }
}

function userService($http, API) {

  $http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;';
  $http.defaults.transformRequest = [function(data) {
      return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;
    }];

  var self = this;

  self.login = function(username, pwd, ctrl) {
    ctrl.requestdata = API + '/winauth' + '; with ' + username;
    return $http.post(API + '/winauth', {
        username: username,
        pwd: pwd
      })
  };

  var param = function(obj) {
    var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

    for(name in obj) {
      value = obj[name];

      if(value instanceof Array) {
        for(i=0; i<value.length; ++i) {
          subValue = value[i];
          fullSubName = name + '[' + i + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value instanceof Object) {
        for(subName in value) {
          subValue = value[subName];
          fullSubName = name + '[' + subName + ']';
          innerObj = {};
          innerObj[fullSubName] = subValue;
          query += param(innerObj) + '&';
        }
      }
      else if(value !== undefined && value !== null)
        query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
    }

    return query.length ? query.substr(0, query.length - 1) : query;
  };

}

function LoginCtrl(user) {
  var self = this;

  function handleRequest(res) {
    self.responsedata = res;
    self.message = res.data.message;

    var authToken = res.data.auth_token;
    localStorage.setItem('token', authToken);
  }

  self.login = function() {
    this.requestdata = 'Starting request...';
    user.login(self.username, self.pwd, self)
      .then(handleRequest, handleRequest)
  }
}

// Login Module
var login = angular.module('login', ["ui.router"])

login.factory('authInterceptor', authInterceptor)
login.service('user', userService)
login.service('auth', authService)
login.constant('API', 'http://myserver.com/api')

EDIT - Я добавил это в свой контроллер входа, чтобы указать маршруты входа

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

  $httpProvider.interceptors.push('authInterceptor');

  $urlRouterProvider.otherwise('/login');

  $stateProvider
  // HOME STATES AND NESTED VIEWS ========================================
  .state('login', {
    url: '/login',
    templateUrl: 'login/login.html',
    controller: "mainLogin",
    controllerAs: "log"
  })           
  // nested list with just some random string data
  .state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/dashboard.html',
  })

})

login.controller('mainLogin', LoginCtrl)

Вот мой index.html:

EDIT - Я удалил "ng-include" и добавил "ng-view" для управления маршрутами.

<body ng-app="login" ng-controller="mainLogin as log" class="loginPage">

  <div class="main" ui-view></div>

</body>

Как вы можете видеть, у меня есть функция, которая проверяет токен в локальном хранилище пользователей:

function authService(auth) {
  var self = this;
  self.isAuthed = function() {
    localStorage.getItem('token');
  }
}

И я загружаю его в модуль как услугу:

login.service('auth', authService)

Вот где я застрял. Я не знаю, куда идти отсюда. Я даже не знаю, правильно ли использую функцию authService. Я все еще многому учусь об AngularJS, поэтому мне легко застрять.:)

Еще одна вещь, которую вы заметите, - это мой файл index.html. Я просто по умолчанию загружаю "login/login.html". Мне нужно загрузить либо login.html, либо dashboard.html в зависимости от того, вошли ли они в систему или нет. А затем также проведите их до dashboard.html, как только они успешно войдут в систему.

script отлично работает, ударяя API аутентификации, аутентифицируя пользователя, а затем сохраняя действительный ключ авторизации в своем локальном хранилище.

Кто-нибудь знает, как я могу это сделать?

4b9b3361

Ответ 1

Есть две отдельные проблемы, с которыми вы сталкиваетесь. Во-первых, это возможность определить, если вы вошли в систему. Предполагая, что пользователь должен войти в систему для любого состояния, кроме состояния входа, вы бы реализовали его так, прослушивая события $stateChangeState и проверяя, что пользователь зарегистрирован в:

login.run(function($state, authService) {
    $rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
        var authToken = authService.isAuthed();
        if (!authToken && toState !== 'login') {
            //not logged in, so redirect to the login view instead of the view
            //the user was attempting to load
            event.preventDefault();
            $state.go('login');

        } 
    })
});

Это поместит их в состояние входа, если они еще не вошли в систему.

Вторая часть - перенаправить на правильный вид после входа в систему, который вы сделали бы в своем контроллере входа:

function LoginCtrl(user, $state) {
    var self = this;

    function handleRequest(res) {
        self.responsedata = res;
        self.message = res.data.message;

        var authToken = res.data.auth_token;
        localStorage.setItem('token', authToken);

        //after successful login, redirect to dashboard
        $state.go('dashboard');
    }

    self.login = function() {
        this.requestdata = 'Starting request...';
        user.login(self.username, self.pwd, self)
                .then(handleRequest, handleRequest)
    }
}

Ответ 2

ok Я вижу, что вы используете ui.router, поэтому давайте работать в этой структуре.

Вы хотите

  • проверить, зарегистрирован ли пользователь
  • перенаправить пользователя в представление

То, что вы ищете, это resolve:{loggedIn: checkLoggedInFn}

чтобы ваш маршрут для панели инструментов мог быть чем-то вроде

.state('dashboard', {
 url: '/dashboard',
 templateUrl: 'dashboard/dashboard.html',
 resolve: {
    loggedIn: function(){
       //do your checking here
    }
  }
})

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

if(!loggedIn){
   $state.go('login');
}

Ответ 3

Вы можете обрабатывать логику внутри своего логина входа в систему:

 self.login = function() {
    this.requestdata = 'Starting request...';
    user.login(self.username, self.pwd, self)
      .then(handleRequest, handleRequest)
  }

Внутри обратного вызова для успеха при входе в систему вы просто сделаете изменение состояния, чтобы отправить пользователя в правильное состояние.

Ответ 4

В authInterceptor добавьте код для ответа. Итак:

return {
    request: function(config) {

        if(config.url.indexOf(API) === 0) {
        request.headers = request.headers || {};
        request.headers['X-PCC-API-TOKEN'] =  localStorage.getItem('token');
        }

        return config;
    },
    response: function(response) {

        //ok response - code 200

        return response;
    },
    responseError: function(response){

       //wrong response - different response code
    }
};

На стороне сервера проверьте HTTP-заголовок X-PCC-API-TOKEN, а если нет (отсутствие аутентификации), ответ должен иметь другой код, например 403. Таким образом, метод responseError будет работать в перехватчике.

    responseError: function(response){

       //wrong response - different response code
       if (response.status === 403) {
            alert("No rights to page");//your code for no auth

            //redirect to different route
            $injector.get('$state').transitionTo('login');//use injector service            
            return $q.reject(response);//return rejection - use $q
        }

    }

Ответ 5

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

function authService(auth) {
  var self = this;
  self.isAuthed = function() {       
   return localStorage.getItem('token');
  }
}
 //here you can inject your auth service to get it work as you want
function LoginCtrl(user, auth) {
  var self = this;

  function handleRequest(res) {
    self.responsedata = res;
    self.message = res.data.message;

    var authToken = res.data.auth_token;
    localStorage.setItem('token', authToken);
  }

  self.login = function() {
    this.requestdata = 'Starting request...';
    user.login(self.username, self.pwd, self)
      .then(handleRequest, handleRequest)
  }
}
login.service('auth', authService)

Ответ 6

function authService(auth) {
var self = this;
self.isAuthed = function() {
**localStorage.getItem('token');**
}  
}

Где вы получаете элемент localstorage? Недостаток LValue отсутствует.

На самом базовом уровне вы можете обработать чек для этого элемента - токена - на странице Dashboard во время загрузки страницы и если она равна null, т.е. пустым, затем перенаправить/направить пользователя на страницу входа. Btw, используйте sessionStorage, а не localStorage, поскольку первая будет скрываться, как только закрывается сеанс браузера.

Есть более элегантные и более простые способы достижения этого, например Passport. вы проверили? Это так просто:

app.post('/login', passport.authenticate('local', { successRedirect: '/',
failureRedirect:'/login'}));

Ответ 7

Ваш код не проверяет изменения URL или затрагивает маршруты поперечным способом.

Помните, что аутентификация и авторизация являются сквозными проблемами. При этом Angular имеет возможность перехватить вызовы маршрутизации, прослушивая $routeChangeStart. Ваш "перехватчик" должен быть добавлен туда. Затем вы можете перенаправить маршрутизатор на требуемый вид, выполнив ручную маршрутизацию. Посмотрите как решение из предыдущего потока.

Ответ 8

Существует простой способ добиться того, что вы хотите для своего приложения, используя PassportJs.

Документация довольно проста и проста в реализации.

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

Ответ 9

Простым способом это просто использовать https://github.com/Emallates/ng-enoa-auth. Вам просто нужно включить его в свое приложение, ничего больше.