这篇文章摘self 关于url路由授权和元素安全here的博客文章,但我将简要总结要点:-)
Security in frontend web application is merely a starting measure to stop Joe Public, however any user with some web knowledge can circumvent it so you should always have security server-side as well.
angular中有关安全性的主要问题是路由安全,幸运的是,在angular中定义路由时,您正在创建一个对象,一个可以具有其他属性的对象.我的方法的基础是在这个路由对象中添加一个安全对象,它基本上定义了用户访问特定路由所必须的角色.
// route which requires the user to be logged in and have the 'Admin' or 'UserManager' permission
$routeProvider.when('/admin/users', {
controller: 'userListCtrl',
templateUrl: 'js/modules/admin/html/users.tmpl.html',
access: {
requiresLogin: true,
requiredPermissions: ['Admin', 'UserManager'],
permissionType: 'AtLeastOne'
});
整个方法的重点是授权服务,它基本上是判断用户是否拥有所需的权限.该服务将问题从该解决方案的其他部分抽象出来,与用户及其在登录期间从服务器检索到的实际权限有关.虽然代码非常冗长,但在我的博客文章中有详细的解释.然而,它基本上处理许可判断和两种授权模式.第一个是用户必须至少拥有其中一个已定义的权限,第二个是用户必须拥有所有已定义的权限.
angular.module(jcs.modules.auth.name).factory(jcs.modules.auth.services.authorization, [
'authentication',
function (authentication) {
var authorize = function (loginRequired, requiredPermissions, permissionCheckType) {
var result = jcs.modules.auth.enums.authorised.authorised,
user = authentication.getCurrentLoginUser(),
loweredPermissions = [],
hasPermission = true,
permission, i;
permissionCheckType = permissionCheckType || jcs.modules.auth.enums.permissionCheckType.atLeastOne;
if (loginRequired === true && user === undefined) {
result = jcs.modules.auth.enums.authorised.loginRequired;
} else if ((loginRequired === true && user !== undefined) &&
(requiredPermissions === undefined || requiredPermissions.length === 0)) {
// Login is required but no specific permissions are specified.
result = jcs.modules.auth.enums.authorised.authorised;
} else if (requiredPermissions) {
loweredPermissions = [];
angular.forEach(user.permissions, function (permission) {
loweredPermissions.push(permission.toLowerCase());
});
for (i = 0; i < requiredPermissions.length; i += 1) {
permission = requiredPermissions[i].toLowerCase();
if (permissionCheckType === jcs.modules.auth.enums.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 === jcs.modules.auth.enums.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 ?
jcs.modules.auth.enums.authorised.authorised :
jcs.modules.auth.enums.authorised.notAuthorised;
}
return result;
};
既然路由具有安全性,您需要一种方法来确定当路由更改开始时,用户是否可以访问该路由.为此,我们将拦截路由更改请求,判断路由对象(上面有我们的新访问对象),如果用户无法访问视图,我们将用另一个替换路由.
angular.module(jcs.modules.auth.name).run([
'$rootScope',
'$location',
jcs.modules.auth.services.authorization,
function ($rootScope, $location, authorization) {
$rootScope.$on('$routeChangeStart', function (event, next) {
var authorised;
if (next.access !== undefined) {
authorised = authorization.authorize(next.access.loginRequired,
next.access.permissions,
next.access.permissionCheckType);
if (authorised === jcs.modules.auth.enums.authorised.loginRequired) {
$location.path(jcs.modules.auth.routes.login);
} else if (authorised === jcs.modules.auth.enums.authorised.notAuthorised) {
$location.path(jcs.modules.auth.routes.notAuthorised).replace();
}
}
});
}]);
这里的关键真的是"安全".replace()'这会将当前路由(他们无权查看的路由)替换为我们将其重定向到的路由.这一站任何人都可以回到未经授权的路由.
现在我们可以拦截路由,我们可以做很多很酷的事情,包括如果用户登陆到他们需要登录的路由上,我们可以做redirecting after a login件事.
解决方案的第二部分是能够根据用户的权限向用户隐藏/显示UI元素.这是通过一个简单的指令实现的.
angular.module(jcs.modules.auth.name).directive('access', [
jcs.modules.auth.services.authorization,
function (authorization) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var makeVisible = function () {
element.removeClass('hidden');
},
makeHidden = function () {
element.addClass('hidden');
},
determineVisibility = function (resetFirst) {
var result;
if (resetFirst) {
makeVisible();
}
result = authorization.authorize(true, roles, attrs.accessPermissionType);
if (result === jcs.modules.auth.enums.authorised.authorised) {
makeVisible();
} else {
makeHidden();
}
},
roles = attrs.access.split(',');
if (roles.length > 0) {
determineVisibility(true);
}
}
};
}]);
然后,您可以确定这样一个元素:
<button type="button" access="CanEditUser, Admin" access-permission-type="AtLeastOne">Save User</button>
阅读我的full blog post篇文章,了解该方法更详细的概述.