7

我正在创建一个Web应用程序,它将满足用户的两个要求。注意:我是AngularJS作为Web开发平台的新手。如何在AngularJS中处理基于角色的授权?

前端 - 1:它的搜索功能,用户可以根据关键字搜索和过滤器搜索特定的文档和研究。这已经使用MySQL实现,用于使用AngularJS获取数据和显示。

前端 - 2:用户可以选择在Web应用程序上创建一个帐户。帐户的目的是:

  1. 保存他们的搜索查询。
  2. 如果管理员将每个用户与特定角色相关联,那么这些用户将可以访问其他选项,例如修改数据库中存在的文档以及上传新文档和主持其他页面。

我的问题:

如何处理基于角色的授权在AngularJS?我无法弄清楚如何创建一个框架,其中包括以下功能: - 用户可以得到与之关联 一个角色 - 访问的页面或不与

我读到了这些角色相关联的功能防止用户在几篇SO文章以及教程中,但每篇教程都以作者说,基于角色的授权应该在服务器端进行处理,我明白为什么这是真的。

如果任何人都可以将我指向教程或者在服务器端为AngularJS实现基于角色的授权的书写,那将会很棒。

谢谢!

回答

10

我在后端以及前端使用基于角色的授权。由于我使用的UI的路由器进行路由选择,我发现(并提高了我的需求)的最佳资源是这篇文章:

链接过期

如果使用UI路由器,肯定检查出来。基本上你需要设置你的路由安全并拦截所有的路由改变。如果用户没有访问其后的内容的权限,则该文章还包含用于隐藏用户界面元素的指令。


编辑:添加一些代码。

首先,您需要将用户权限存储在某个地方,例如,在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

谢谢@ SH-ADO-W,我会实现你所提到的这个解决方案。我会让你知道,如果它运作或没有。 – CalmWinds

+2

链接不再工作。最好在SO中发布内容,而不是在其外部链接。 – eabates

+1

我添加了我的应用程序中的代码,我相信这是基于该文章的。 – Adrian

相关问题