這些天我們忙於應用的前端工作,我們主要使用angular完成的。最近的一個需求是基於角色訪問GUI。一個用戶可以有多個角色,而它應只能訪問授權給他的那一部分GUI。
我們主要通過在2個層次限制應用的GUI訪問,來解決上述需求:
一個用戶只能訪問授權給他的頁面(或者說流量)
在一個頁面上,用戶只能看到授權給他的那部分。
要解決上述需求1,我們捕捉路有變化事件並對每一路由變化進行檢查,看用戶是否授權訪問下一路由,保證他不會看到拒絕訪問的頁面
$rootScope.$on(
"$routeChangeStart"
,
function
(event, next, current) {
if
(!authService.isUrlAccessibleForUser(next.originalPath))
$location.path(
'/authError'
);
});
上面的authService 是我們創建的一個服務,它有角色用戶列表,並給授權用戶路由流量。函數isUrlAccessibleForUser() 將檢查分配的用戶是否可以訪問給定流量並返回true或false.
服務將 從後台和路由訪問信息中獲取一個用戶的角色列表,每個角色將保存在服務本身的一個Map集合中。(關於用戶和角色的一些細節可以存到數據局,通過後台的方式獲取)
app.factory(
'authService'
,
function
($http) {
var
userRole = [];
// obtained from backend
var
userRoleRouteMap = {
'ROLE_ADMIN'
: [
'/dashboard'
,
'/about-us'
,
'/authError'
],
'ROLE_USER'
: [
'/usersettings'
,
'/usersettings/personal'
,
'/authError'
]
};
return
{
userHasRole:
function
(role) {
for
(
var
j = 0; j < userRole.length; j++) {
if
(role == userRole[j]) {
return
true
;
}
}
return
false
;
},
isUrlAccessibleForUser:
function
(route) {
for
(
var
i = 0; i < userRole.length; i++) {
var
role = userRole[i];
var
validUrlsForRole = userRoleRouteMap[role];
if
(validUrlsForRole) {
for
(
var
j = 0; j < validUrlsForRole.length; j++) {
if
(validUrlsForRole[j] == route)
return
true
;
}
}
}
return
false
;
}
};
});
這將解決上述需求的第一點,對於需求的第二點我們來創建一條指令。這個指令信息類似以下:
<
div
my-access=”ROLE_ADMIN”>......</
div
>
如果用戶有 ROLE_ADMIN 的這個角色的時候,將以上的html標簽將被加載到html的頁面中,否則將 這個 Html標簽從 頁面中移除。
指令的實現代碼如下:
.directive(
'myAccess'
, [
'authService'
,
'removeElement'
,
function
(authService, removeElement) {
return
{
restrict:
'A'
,
link:
function
(scope, element, attributes) {
var
hasAccess =
false
;
var
allowedAccess = attributes.myAccess.split(
" "
);
for
(i = 0; i < allowedAccess.length; i++) {
if
(authService.userHasRole(allowedAccess[i])) {
hasAccess =
true
;
break
;
}
}
if
(!hasAccess) {
angular.forEach(element.children(),
function
(child) {
removeElement(child);
});
removeElement(element);
}
}
}
}]).constant(
'removeElement'
,
function
(element){
element && element.remove && element.remove();
});
這一辦法是很簡潔的,而我們在GUI上很巧妙的實現了用戶授權. 一個潛在的問題是,如果UI的渲染器在你從後台獲取用戶角色之前就已經在運行了,那麼該HTML中所有帶上該指令的部分都會從html中被移除掉. 這對於我們而言不是個麻煩,因為我們會在登錄完成之時就獲取到了用戶角色的詳細信息。而如果這一問題對你而言是個問題的話,解決方案可以是這樣:如果用戶角色還沒有獲取到,就只是隱藏這些html元素,僅等到你獲取到角色列表之後再按照授權0信息將它們移除掉. 同時還請注意不能因為有了一個GUI的訪問控制,就省掉了後台固有的安全實現.
達者廣交,分享為先!
帶你走近AngularJS系列:
如何在 AngularJS 中對控制器進行單元測試 http://www.linuxidc.com/Linux/2013-12/94166.htm
在 AngularJS 應用中通過 JSON 文件來設置狀態 http://www.linuxidc.com/Linux/2014-07/104083.htm
AngularJS 之 Factory vs Service vs Provider http://www.linuxidc.com/Linux/2014-05/101475.htm
AngularJS —— 使用 ngResource、RESTful APIs 和 Spring MVC 框架提交數據 http://www.linuxidc.com/Linux/2014-07/104402.htm
AngularJS 的詳細介紹:請點這裡
AngularJS 的下載地址:請點這裡