如何使用AngularFire实现基于角色的访问控制 [英] How to implement a role based access control with AngularFire
问题描述
我的理解是我需要执行以下步骤:
My understanding is that I need to undertake the following steps:
- 将用户角色设为只读
- 对访问角色以控制访问的数据使用安全规则
- 检查路由器中的角色
官方文档中有各种关于如何处理安全规则的例子,但我无法弄清楚如何检查路由器中的角色。我们假设我有一个仅限管理员的区域,如果非管理员的某个人试图访问该页面,我希望该用户被重定向。
There are various examples on the official documentation how to deal with the security rules, but I couldn't figure out how to check for the role in the router. Let's assume I have an admin-only area, if someone who is not an admin tries to access that page I want that user to be redirected.
我正在关注使用UI-Router的官方示例,这是我的代码:
I'm currently following the official example using UI-Router, so this is my code:
app.config(["$stateProvider", function ($stateProvider) {
$stateProvider
.state("home", {
// the rest is the same for ui-router and ngRoute...
controller: "HomeCtrl",
templateUrl: "views/home.html",
resolve: {
// controller will not be loaded until $waitForSignIn resolves
// Auth refers to our $firebaseAuth wrapper in the factory below
"currentAuth": ["Auth", function(Auth) {
// $waitForSignIn returns a promise so the resolve waits for it to complete
return Auth.$waitForSignIn();
}]
}
})
.state("account", {
// the rest is the same for ui-router and ngRoute...
controller: "AccountCtrl",
templateUrl: "views/account.html",
resolve: {
// controller will not be loaded until $requireSignIn resolves
// Auth refers to our $firebaseAuth wrapper in the factory below
"currentAuth": ["Auth", function(Auth) {
// $requireSignIn returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.$requireSignIn();
}]
}
});
}]);
我猜我必须检查用户角色的决心,但是怎么会我从那里访问数据库中的数据?
I'm guessing I'll have to check in the resolve for a user role, but how would I access the data from the database there?
更新:
我试过André的解决方案,但waitForAuth(console.log(test1)永远不会触发。waitForSignIn虽然有,但没有任何反应 - 没有错误消息。
I tried André's solution, but "waitForAuth" (console.log("test1") never triggers. "waitForSignIn" does though, but then nothing happens - there is no error message.
.state('superadmin-login', {
url: '/superadmin',
templateUrl: 'views/superadmin-login.html',
'waitForAuth': ['Auth', function (Auth) {
console.log('test1');
// $requireAuth returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.refAuth().$waitForSignIn();
}],
})
.state('superadmin', {
url: '/center-of-the-universe',
templateUrl: 'views/superadmin.html',
resolve: {
// YOUR RESOLVES GO HERE
// controller will not be loaded until $requireAuth resolves
// Auth refers to our $firebaseAuth wrapper in the example above
'currentAuth': ['Auth', function (Auth) {
console.log('test2');
// $requireAuth returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.refAuth().$requireSignIn();
}],
//Here i check if a user has admin rights, note that i pass currentAuth and waitForAuth to this function to make sure those are resolves before this function
hasAdminAccess: function (currentAuth, waitForAuth, Rights) {
console.log('test');
return Rights.hasAdminAccess(currentAuth);
}
}
})
推荐答案
以下是我的表现。
首先我做了一个工厂来检查用户是否拥有正确的权利:
First i made a factory to check if the user has the correct rights:
angular.module('rights.services', [])
.factory('Rights', function ($q) {
var ref = firebase.database().ref();
return {
hasAdminAccess: function (user) {
var deferred = $q.defer();
ref.child("Rights").child("Admin").child(user.uid).once('value').then(function (snapshot) {
if (snapshot.val()) {
deferred.resolve(true);
}
else{
deferred.reject("NO_ADMIN_ACCESS");
}
});
return deferred.promise;
}
};
});
其次我在决议中使用这个工厂:
And secondly i use this factory inside the resolve:
.state('logged', {
url: '',
abstract: true,
templateUrl: helper.basepath('app.html'),
resolve: {
// YOUR RESOLVES GO HERE
// controller will not be loaded until $requireAuth resolves
// Auth refers to our $firebaseAuth wrapper in the example above
"currentAuth": ["Auth", function (Auth) {
// $requireAuth returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.refAuth().$requireSignIn();
}],
"waitForAuth": ["Auth", function (Auth) {
// $requireAuth returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.refAuth().$waitForSignIn();
}],
//Here i check if a user has admin rights, note that i pass currentAuth and waitForAuth to this function to make sure those are resolves before this function
hasAdminAccess: function (currentAuth, waitForAuth, Rights) {
return Rights.hasLightAccess(currentAuth);
}
})
})
请记住在firebase中保存用户角色的方式可能与我在此示例中的方式不同。这是(部分)它在firebase中的样子:
Keep in mind the way you save user roles in firebase can be different from how i do it in this example. This is (part of) how it looks in firebase:
{"moderators":
{
"0123eeca-ee0e-4ff1-9d13-43b8914999a9" : true,
"3ce9a153-eea8-498f-afad-ea2a92d79950" : true,
"571fa880-102d-4372-be8d-328ed9e7c9de" : true
}
},
{"Admins":
{
"d3d4effe-318a-43e1-a7b6-d7faf3f360eb" : true
}
}
以及这些节点的安全规则:
And the security rules for these nodes:
"Admins": {
"$uid": {
//No write rule so admins can only be added inside the firebase console
".read": "auth != null && auth.uid ==$uid"
}
},
"Moderators" : {
//Admins are able to see who the moderators are and add/delete them
".read" : "(auth != null) && (root.child('Admins').hasChild(auth.uid))",
".write" : "(auth != null) && (root.child('Admins').hasChild(auth.uid))",
"$uid": {
".read": "auth != null && auth.uid ==$uid"
}
}
这篇关于如何使用AngularFire实现基于角色的访问控制的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!