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

相關問題