如何在 AngularJS 中处理基于角色的授权?
Posted
技术标签:
【中文标题】如何在 AngularJS 中处理基于角色的授权?【英文标题】:How to handle role based authorization in AngularJS? 【发布时间】:2016-01-27 05:44:41 【问题描述】:我正在创建一个 Web 应用程序,它将满足用户的两个要求。注意:我是 AngularJS 作为 Web 开发平台的新手。
前端 - 1:它是一种搜索功能,用户可以根据关键字搜索和过滤器搜索特定文档和研究。这是使用 mysql 实现的,用于使用 AngularJS 获取数据和显示。
前端 - 2:用户可以选择在网络应用程序上创建帐户。该帐户的用途是:
-
保存他们的搜索查询。
如果管理员将每个用户与特定角色相关联,那么这些用户将可以访问额外的选项,例如修改数据库中的文档以及上传新文档和其他页面的主机。
我的问题:
我无法弄清楚如何创建一个涉及以下功能的框架: - 用户获得与他们相关的角色 - 阻止用户访问与这些角色无关的页面或功能
我已经阅读了一些 SO 文章和教程,但每个教程都以作者说基于角色的授权应该在服务器端处理,我理解为什么这是真的。
如果有人可以向我指出在 AngularJS 的服务器端实现了基于角色的授权的教程或文章,那就太好了。
谢谢!
【问题讨论】:
【参考方案1】:我在后端和前端都使用基于角色的授权。由于我使用 UI-Router 进行路由,因此我发现(并根据我的需要进行了改进)的最佳资源是这篇文章:
链接已过期
如果您使用 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');
);
)();
【讨论】:
谢谢@sh-ado-w,我将实施您上面提到的解决方案。我会告诉你是否成功。 链接不再起作用。最好在 SO 中发布内容而不是在其外部链接。 我从我的应用程序中添加了我相信基于那篇文章的代码。以上是关于如何在 AngularJS 中处理基于角色的授权?的主要内容,如果未能解决你的问题,请参考以下文章