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

Я новичок в AngularJS и прошел через их учебник и почувствовал это.

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

Что я хочу сделать
a.) Я хочу иметь одну страницу для моего проекта http://myproject.com.
б). Когда пользователь набирает URL-адрес в браузере, на основании того, был ли пользователь зарегистрирован или нет, ему предоставляется домашняя страница/просмотр или страница входа/просмотра под тем же URL-адресом http://myproject.com.
c.), если пользователь не вошел в систему, он заполняет форму и сервер устанавливает сеанс USER_TOKEN в сеансе, поэтому все дальнейшие запросы к конечным точкам будут аутентифицированы на основе USER_TOKEN

Мои путаницы
a.) Как я могу обрабатывать аутентификацию на стороне клиента, используя AngularJS? Я видел здесь и здесь, но не понял, как их использовать
б.) Как я могу представить разные представления пользователю на основе того, был ли пользователь зарегистрирован или нет под тем же адресом URL http://myproject.com

Я использую angular.js в первый раз и действительно путаюсь, как начать. Любые советы и/или ресурсы очень ценятся.

Ответ 1

Мне нравится подход и реализован на серверной стороне без каких-либо действий, связанных с аутентификацией, на интерфейсе

Моя "техника" в моем последнем приложении - это... клиент не заботится о Авт. Для каждой вещи в приложении требуется сначала войти в систему, поэтому сервер всегда будет обслуживать страницу входа, если только существующий пользователь не обнаруженных в сеансе. Если session.user найден, сервер просто отправляет index.html. Bam: -o

Ищите комментарий от "Andrew Joslin".

https://groups.google.com/forum/?fromgroups=#!searchin/angular/authentication/angular/POXLTi_JUgg/VwStpoWCPUQJ

Ответ 2

Я создал репозиторий github, суммирующий эту статью в основном: https://medium.com/opinionated-angularjs/techniques-for-authentication-in-angularjs-applications-7bbf0346acec

ng-login Github repo

Plunker

Я постараюсь объяснить как можно больше, надеюсь, что я помогу некоторым из вас там:

(1) app.js: Создание констант проверки подлинности при определении приложения

var loginApp = angular.module('loginApp', ['ui.router', 'ui.bootstrap'])
/*Constants regarding user login defined here*/
.constant('USER_ROLES', {
    all : '*',
    admin : 'admin',
    editor : 'editor',
    guest : 'guest'
}).constant('AUTH_EVENTS', {
    loginSuccess : 'auth-login-success',
    loginFailed : 'auth-login-failed',
    logoutSuccess : 'auth-logout-success',
    sessionTimeout : 'auth-session-timeout',
    notAuthenticated : 'auth-not-authenticated',
    notAuthorized : 'auth-not-authorized'
})

(2) Auth Service: В службе auth.js реализованы все следующие функции. Служба $http используется для связи с сервером для процедур аутентификации. Также содержит функции авторизации, то есть, если пользователю разрешено выполнить определенное действие.

angular.module('loginApp')
.factory('Auth', [ '$http', '$rootScope', '$window', 'Session', 'AUTH_EVENTS', 
function($http, $rootScope, $window, Session, AUTH_EVENTS) {

authService.login() = [...]
authService.isAuthenticated() = [...]
authService.isAuthorized() = [...]
authService.logout() = [...]

return authService;
} ]);

(3) Сессия: Одиночный символ для хранения пользовательских данных. Реализация здесь зависит от вас.

angular.module('loginApp').service('Session', function($rootScope, USER_ROLES) {

    this.create = function(user) {
        this.user = user;
        this.userRole = user.userRole;
    };
    this.destroy = function() {
        this.user = null;
        this.userRole = null;
    };
    return this;
});

(4) Родительский контроллер:. Рассматривайте это как "основную" функцию вашего приложения, все контроллеры наследуют от этого контроллера и являются основой аутентификации этого приложения.

<body ng-controller="ParentController">
[...]
</body>

(5) Контроль доступа: Чтобы запретить доступ к определенным маршрутам, необходимо выполнить 2 шага:

a) Добавьте данные о ролях, разрешенных для доступа к каждому маршруту, в службе ui router $stateProvider, как показано ниже (то же самое можно использовать для ngRoute).

.config(function ($stateProvider, USER_ROLES) {
  $stateProvider.state('dashboard', {
    url: '/dashboard',
    templateUrl: 'dashboard/index.html',
    data: {
      authorizedRoles: [USER_ROLES.admin, USER_ROLES.editor]
    }
  });
})

b) В $rootScope. $on ('$ stateChangeStart') добавляет функцию, чтобы предотвратить изменение состояния, если пользователь не авторизовался.

$rootScope.$on('$stateChangeStart', function (event, next) {
    var authorizedRoles = next.data.authorizedRoles;
    if (!Auth.isAuthorized(authorizedRoles)) {
      event.preventDefault();
      if (Auth.isAuthenticated()) {
        // user is not allowed
        $rootScope.$broadcast(AUTH_EVENTS.notAuthorized);
      } else {
        // user is not logged in
        $rootScope.$broadcast(AUTH_EVENTS.notAuthenticated);
      }
    }
});

(6) Auth-перехватчик: Это реализовано, но не может быть проверено в области действия этого кода. После каждого запроса $http этот перехватчик проверяет код состояния, если возвращается один из приведенных ниже, затем он передает событие, чтобы заставить пользователя снова войти в систему.

angular.module('loginApp')
.factory('AuthInterceptor', [ '$rootScope', '$q', 'Session', 'AUTH_EVENTS',
function($rootScope, $q, Session, AUTH_EVENTS) {
    return {
        responseError : function(response) {
            $rootScope.$broadcast({
                401 : AUTH_EVENTS.notAuthenticated,
                403 : AUTH_EVENTS.notAuthorized,
                419 : AUTH_EVENTS.sessionTimeout,
                440 : AUTH_EVENTS.sessionTimeout
            }[response.status], response);
            return $q.reject(response);
        }
    };
} ]);

P.S. Ошибка с автозаполнением данных формы, как указано в 1-й статье, можно легко избежать, добавив директиву, включенную в директивы .js.

P.S.2 Этот код может быть легко изменен пользователем, чтобы можно было видеть разные маршруты или отображать содержимое, которое не предназначалось для отображения. Логика ДОЛЖНА быть реализована на стороне сервера, это всего лишь способ правильно показать вещи в вашем ng-приложении.

Ответ 3

Я сделал быстрый скринкаст по этому вопросу. Проводит вас через концепцию того, как вы внедряете систему auth в свой SPA и соединяете ее с вашим API. https://www.youtube.com/watch?v=ZHMVP5aLAPM

Ответ 4

Я ответил на аналогичный вопрос: AngularJS Authentication + RESTful API


Я написал модуль AngularJS для UserApp, который поддерживает защищенные/общедоступные маршруты, перенаправление при входе в систему/выходе из системы, сердцебиения для проверки состояния, сохранение токена сеанса в файле cookie, событиях и т.д.

Вы можете:

  • Измените модуль и добавьте его в свой собственный API или
  • Используйте модуль вместе с UserApp (облачный API управления пользователями)

https://github.com/userapp-io/userapp-angular

Если вы используете UserApp, вам не нужно будет писать какой-либо серверный код для пользовательских материалов (более чем проверку маркера). Возьмите курс по Codecademy, чтобы попробовать.

Вот несколько примеров того, как это работает:

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

    $routeProvider.when('/login', {templateUrl: 'partials/login.html', public: true, login: true});
    $routeProvider.when('/signup', {templateUrl: 'partials/signup.html', public: true});
    $routeProvider.when('/home', {templateUrl: 'partials/home.html'});
    

    Маршрут .otherwise() должен быть установлен в том месте, где вы хотите, чтобы ваши пользователи были перенаправлены после входа в систему. Пример:

    $routeProvider.otherwise({redirectTo: '/home'});

  • Форма входа с обработкой ошибок:

    <form ua-login ua-error="error-msg">
        <input name="login" placeholder="Username"><br>
        <input name="password" placeholder="Password" type="password"><br>
        <button type="submit">Log in</button>
        <p id="error-msg"></p>
    </form>
    
  • Регистрация формы с обработкой ошибок:

    <form ua-signup ua-error="error-msg">
      <input name="first_name" placeholder="Your name"><br>
      <input name="login" ua-is-email placeholder="Email"><br>
      <input name="password" placeholder="Password" type="password"><br>
      <button type="submit">Create account</button>
      <p id="error-msg"></p>
    </form>
    
  • Выход из системы:

    <a href="#" ua-logout>Log Out</a>

    (Завершает сеанс и перенаправляет маршрут входа в систему)

  • Доступ к свойствам пользователя:

    Доступ к свойствам пользователя осуществляется с помощью службы user, например: user.current.email

    Или в шаблоне: <span>{{ user.email }}</span>

  • Скрыть элементы, которые должны отображаться только при входе в систему:

    <div ng-show="user.authorized">Welcome {{ user.first_name }}!</div>

  • Показать элемент на основе разрешений:

    <div ua-has-permission="admin">You are an admin</div>

Чтобы аутентифицировать ваши внутренние службы, просто используйте user.token(), чтобы получить токен сеанса и отправить его с помощью запроса AJAX. В фоновом режиме используйте UserApp API (если вы используете UserApp), чтобы проверить, действителен ли токен.

Если вам нужна помощь, просто дайте мне знать!

Ответ 5

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

Как любой, кто новичок в этой технологии и хочет аутентифицировать "Пользователь", я предлагаю сделать это с помощью возможности С# web api. для этого вы можете использовать спецификацию OAuth, которая поможет вам создать надежный механизм безопасности для аутентификации пользователя. как только вы создадите WebApi с помощью OAuth, вам нужно вызвать этот api для токена:

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };
 

Ответ 6

Я думаю, что каждый ответ JSON должен содержать свойство (например, {authenticated: false}), и клиент должен его проверять каждый раз: если false, то контроллер/служба Angular будет перенаправляться на страницу входа.

И что произойдет, если пользователь поймает JSON и изменит bool на True?

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

Ответ 7

var _login = function (loginData) {
 
        var data = "grant_type=password&username=" + loginData.userName + "&password=" + loginData.password;
 
        var deferred = $q.defer();
 
        $http.post(serviceBase + 'token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }).success(function (response) {
 
            localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
 
            _authentication.isAuth = true;
            _authentication.userName = loginData.userName;
 
            deferred.resolve(response);
 
        }).error(function (err, status) {
            _logOut();
            deferred.reject(err);
        });
 
        return deferred.promise;
 
    };