7

Я создаю веб-приложение, которое удовлетворит два требования для пользователей. Примечание. Я новичок в AngularJS как платформе для веб-разработки.Как обрабатывать авторизацию на основе ролей в AngularJS?

Front-end - 1: его функция поиска, в которой пользователи могут искать конкретные документы и исследования на основе поиска по ключевым словам и фильтров. Это было реализовано с использованием MySQL для извлечения данных и отображения с помощью AngularJS.

Внешняя часть - 2: у пользователей будет возможность создать учетную запись в веб-приложении. Цель счета:

  1. Сохраните свои поисковые запросы.
  2. Если администратор связывает каждого пользователя с определенной ролью, эти пользователи получат доступ к дополнительным параметрам, таким как изменение документов, присутствующих в базе данных, а также загрузка новых документов и узлов других страниц.

Мой вопрос:

Как обрабатывать разрешения на основе ролей в AngularJS? Я не могу понять, как создать структуру, которая включает в себя следующие функциональные возможности: - Пользователи получают определенную роль, связанную с ними - запретить пользователям доступ к страницам или функциональным возможностям, которые не связаны с этими ролями

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

Было бы здорово, если бы кто-нибудь мог указать мне на учебные пособия или рецензии, которые на стороне сервера для ролей на AngularJS реализованы на основе ролей.

Спасибо!

ответ

10

Я использую авторизацию на основе роли как на бэкэнд, так и на интерфейсе. Так как я использую UI-маршрутизатор для маршрутизации, лучший ресурс я нашел (и улучшение моих потребностей) эта статья:

ссылка истек

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


Edit: Добавление некоторого кода.

Во-первых, вам необходимо иметь разрешения пользователя, хранящиеся где-нибудь, например.на пользовательском объекте сериализации в LocalStorage:

{"id":1,"name":"user","created_at":"2016-04-17 18:58:19","gender":"m","roles":["admin"]} 

Затем, у вас есть две важные части:

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

Директива:

(function() { 
    'use strict'; 

    angular 
    .module('app') 
    .directive('access', access); 

    /** @ngInject */ 
    function access(authorization) { 
    var directive = { 
     restrict: 'A', 
     link: linkFunc, 
    }; 

    return directive; 

    /** @ngInject */ 
    function linkFunc($scope, $element, $attrs) { 
     var makeVisible = function() { 
     $element.removeClass('hidden'); 
     }; 

     var makeHidden = function() { 
     $element.addClass('hidden'); 
     }; 

     var determineVisibility = function (resetFirst) { 
     var result; 

     if (resetFirst) { 
      makeVisible(); 
     } 

     result = authorization.authorize(true, roles, $attrs.accessPermissionType); 

     if (result === authorization.constants.authorised) { 
      makeVisible(); 
     } else { 
      makeHidden(); 
     } 
     }; 

     var roles = $attrs.access.split(','); 

     if (roles.length > 0) { 
      determineVisibility(true); 
     } 
    } 
    } 

})(); 

Вам необходимо установить CSS так, чтобы элементы с классом hidden не были видны.

Услуги:

(function() { 
    'use strict'; 

    angular 
    .module('app') 
    .factory('authorization', authorization); 

    /** @ngInject */ 
    function authorization($rootScope) { 
    var service = { 
     authorize: authorize, 
     constants: { 
     authorised: 0, 
     loginRequired: 1, 
     notAuthorised: 2 
     } 
    }; 

    return service; 

    function authorize(loginRequired, requiredPermissions, permissionCheckType) { 
     var result = service.constants.authorised, 
      user = $rootScope.currentUser, 
      loweredPermissions = [], 
      hasPermission = true, 
      permission; 

     permissionCheckType = permissionCheckType || 'atLeastOne'; 

     if (loginRequired === true && user === undefined) { 
      result = service.constants.loginRequired; 

     } else if ((loginRequired === true && user !== undefined) && 
        (requiredPermissions === undefined || requiredPermissions.length === 0)) { 
      result = service.constants.authorised; 

     } else if (requiredPermissions) { 

      loweredPermissions = []; 

      angular.forEach(user.roles, function (permission) { 
       loweredPermissions.push(permission.toLowerCase()); 
      }); 

      for (var i = 0; i < requiredPermissions.length; i += 1) { 
       permission = requiredPermissions[i].toLowerCase(); 

       if (permissionCheckType === 'combinationRequired') { 
        hasPermission = hasPermission && loweredPermissions.indexOf(permission) > -1; 
        // if all the permissions are required and hasPermission is false there is no point carrying on 
        if (hasPermission === false) { 
         break; 
        } 
       } else if (permissionCheckType === 'atLeastOne') { 
        hasPermission = loweredPermissions.indexOf(permission) > -1; 
        // if we only need one of the permissions and we have it there is no point carrying on 
        if (hasPermission) { 
         break; 
        } 
       } 
      } 

      result = hasPermission ? 
        service.constants.authorised : 
        service.constants.notAuthorised; 
     } 

     return result; 
    } 
    } 
})(); 

Теперь вы можете использовать директиву, чтобы показать/скрыть элемент:

<a ui-sref="app.administration" class="btn btn-primary pull-right" access="admin">Administration</a> 

Конечно, это будет только скрыть элемент в DOM, так что вы должны сделать проверка авторизации на сервере.

Эта первая часть решена для отображения/скрытия элементов в пользовательском интерфейсе, но вы также можете защитить маршруты приложений.

Определение маршрута:

(function() { 
    'use strict'; 

    angular 
    .module('app') 
    .config(routeConfig); 

    /** @ngInject */ 
    function routeConfig($stateProvider) { 
    $stateProvider 
     .state('app.dashboard', { 
     url: '/dashboard', 
     data: { 
      access: { 
      loginRequired: true 
      } 
     }, 
     templateUrl: 'template_path', 
     controller: 'DashboardController as vm' 
     } 
    } 
})(); 

и теперь просто проверить разрешение на $stateChangeStart мероприятия

(function() { 
    'use strict'; 

    angular 
    .module('app') 
    .run(runBlock); 

    /** @ngInject */ 
    function runBlock($rootScope, $state, authorization) { 
    $rootScope.$on('$stateChangeStart', function(event, toState) { 
     // route authorization check 
     if (toState.data !== undefined && toState.data.access !== undefined) { 
     authorised = authorization.authorize(toState.data.access.loginRequired, 
              toState.data.access.requiredPermissions, 
              toState.data.access.permissionCheckType); 

     if (authorised === authorization.constants.loginRequired) { 
      event.preventDefault(); 
      $state.go('app.login'); 
     } else if (authorised === authorization.constants.notAuthorised) { 
      event.preventDefault(); 
      $state.go('app.dashboard'); 
     } 
     } 
    }); 
    } 

})(); 
+0

Спасибо @ ш-Адо-ю, я бы реализации этого решения вы уже упоминали выше , Я дам вам знать, если это сработает или нет. – CalmWinds

+2

Ссылка больше не работает. Лучше размещать контент в SO, чем ссылку за его пределами. – eabates

+1

Я добавил код из своей заявки, который, я считаю, основывался на этой статье. – Adrian