【问题标题】:How to implement a role based access control with AngularFire如何使用 AngularFire 实现基于角色的访问控制
【发布时间】:2016-12-27 22:36:46
【问题描述】:

我的理解是我需要进行以下步骤:

  • 将用户角色设为只读
  • 对访问角色的数据使用安全规则来控制访问
  • 检查路由器中的角色

官方文档中有各种如何处理安全规则的示例,但我不知道如何检查路由器中的角色。假设我有一个仅限管理员的区域,如果不是管理员的人尝试访问该页面,我希望该用户被重定向。

我目前正在关注official example using UI-Router,所以这是我的代码:

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();
    }]
  }
});
}]);

我猜我必须检查用户角色的解析,但我将如何访问那里的数据库中的数据?

更新:

我尝试了 André 的解决方案,但 "waitForAuth" (console.log("test1") 永远不会触发。虽然 "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);
        }
    }
})

【问题讨论】:

    标签: javascript firebase angularfire firebase-authentication firebase-security


    【解决方案1】:

    这就是我的做法。

    首先我做了一个工厂来检查用户是否有正确的权限:

    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;
            }
        };
    });
    

    其次,我在 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 中的外观:

    {"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 结构的 sn-p 吗?可能还有安全规则(因为这是确保您的规则得到执行的唯一方法)?
    • 非常感谢您的帮助安德烈,我真的很感激。请参阅上面的更新 - 我不确定我是否因为不使用抽象状态而错误地实施了您的解决方案?
    • @user3255061它与抽象状态无关,但与您的 waitForAuth 处于不同状态这一事实有关。您也可以将其置于其他状态或将其从 hasAdminAccess 函数中删除。那么它应该可以工作了。
    • @AndréKool 喜欢这样:pastebin.com/ufnZW1mr?那是行不通的。还是我误会了你?非常感谢您的帮助。
    猜你喜欢
    • 2020-02-28
    • 2012-12-06
    • 1970-01-01
    • 2020-12-12
    • 2013-10-31
    • 2019-07-05
    • 2010-09-11
    • 2013-08-28
    相关资源
    最近更新 更多