Javascript 如何使用AngularFire实现基于角色的访问控制
我的理解是,我需要采取以下步骤: 将用户角色设置为只读 对访问角色的数据使用安全规则来控制访问 检查路由器中的角色 官方文档中有很多关于如何处理安全规则的例子,但我不知道如何检查路由器中的角色。让我们假设我有一个管理员专区,如果有人不是管理员试图访问该页面,我希望该用户被重定向 我目前正在遵循,因此这是我的代码:Javascript 如何使用AngularFire实现基于角色的访问控制,javascript,firebase,angularfire,firebase-authentication,firebase-security,Javascript,Firebase,Angularfire,Firebase Authentication,Firebase Security,我的理解是,我需要采取以下步骤: 将用户角色设置为只读 对访问角色的数据使用安全规则来控制访问 检查路由器中的角色 官方文档中有很多关于如何处理安全规则的例子,但我不知道如何检查路由器中的角色。让我们假设我有一个管理员专区,如果有人不是管理员试图访问该页面,我希望该用户被重定向 我目前正在遵循,因此这是我的代码: app.config(["$stateProvider", function ($stateProvider) { $stateProvider .state("home", {
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();
}]
}
});
}]);
我猜我必须签入用户角色的解析,但是如何从那里的数据库访问数据呢
更新:
我尝试了安德烈的解决方案,但waitForAuth console.logtest1从未触发。waitForSignIn虽然这样做了,但是什么也没有发生——没有错误消息
.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);
}
}
})
我是这样做的
首先,我制作了一个工厂来检查用户是否拥有正确的权限:
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;
}
};
});
其次,我在解决方案中使用了这个工厂:
.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中的部分外观:
{"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
}
}
以及这些节点的安全规则:
"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"
}
}
我是这样做的
首先,我制作了一个工厂来检查用户是否拥有正确的权限:
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;
}
};
});
其次,我在解决方案中使用了这个工厂:
.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中的部分外观:
{"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
}
}
以及这些节点的安全规则:
"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"
}
}
回答得好,安德烈。能否添加用于权限的JSON结构的片段?还有可能是安全规则,因为这是确保您的规则得到执行的唯一方法?非常感谢您的帮助André,我非常感谢。请参阅上面我的更新-我不确定我是否实现了错误的解决方案,因为我没有使用抽象状态?@user3255061它与抽象状态无关,但与您的waitForAuth处于不同状态这一事实有关。您还可以将其置于其他状态,或从hasAdminAccess函数中将其删除。那么它应该会起作用。@AndréKool喜欢这样:?那不行。还是我误解了你?非常感谢你的帮助。回答得很好,安德烈。能否添加用于权限的JSON结构的片段?还有可能是安全规则,因为这是确保您的规则得到执行的唯一方法?非常感谢您的帮助André,我非常感谢。请参阅上面我的更新-我不确定我是否实现了错误的解决方案,因为我没有使用抽象状态?@user3255061它与抽象状态无关,但与您的waitForAuth处于不同状态这一事实有关。您还可以将其置于其他状态,或从hasAdminAccess函数中将其删除。那么它应该会起作用。@AndréKool喜欢这样:?那不行。还是我误解了你?非常感谢你的帮助。