环回 ACL "Authorization Required"

Loopback ACL "Authorization Required"

我正在使用 Loopback3。我 运行 遇到了我的 ACL 角色的问题,我不确定我做错了什么。我希望特定角色的用户能够将数据写入端点,但出于某种原因,我设置的用户(处于其中一个角色)无法写入。我收到“需要授权”错误。

我有 4 个角色:

对于此端点,所有经过身份验证的用户都可以读取数据,但只有管理员、内部和 bot 用户可以写入数据,只有管理员用户可以删除数据。

以下是我定义 ACL 的方式:

"acls": [
    {
        "accessType": "*",
        "principalType": "ROLE",
        "principalId": "$everyone",
        "permission": "DENY"
    },
    {
        "accessType": "READ",
        "principalType": "ROLE",
        "principalId": "$authenticated",
        "permission": "ALLOW"
    },
    {
        "accessType": "WRITE",
        "principalType": "ROLE",
        "principalId": "admin",
        "permission": "ALLOW"
    },
    {
        "accessType": "WRITE",
        "principalType": "ROLE",
        "principalId": "internal",
        "permission": "ALLOW"
    },
    {
        "accessType": "WRITE",
        "principalType": "ROLE",
        "principalId": "bot",
        "permission": "ALLOW"
    },
    {
        "accessType": "DELETE",
        "principalType": "ROLE",
        "principalId": "admin",
        "permission": "ALLOW"
    }
],

我设置了两个用户,一个是机器人,一个是管理员。当我为任一用户向 API 发出 POST 请求时,我收到 'Authorization Required' 错误,即使是从资源管理器界面执行此操作也是如此。我可以毫无问题地执行 GET,但是 POST 会失败。

如果我删除所有 "WRITE" acl 并用这个替换它们,那么 POST 就可以了。

    {
        "accessType": "WRITE",
        "principalType": "ROLE",
        "principalId": "$authenticated",
        "permission": "ALLOW"
    },

所以,我可以实现它,但我不知道为什么我的自定义角色会失败。

编辑:这是我创建用户的方式,因为我实际上还没有构建任何类型的界面。

module.exports = function (app) {
    let today = new Date();

    let admin = {
        name: 'admin',
        description: 'admin users',
        created: today.toJSON(),
        modified: today.toJSON()
    };

    let internal = {
        name: 'internal',
        description: 'Internal users',
        created: today.toJSON(),
        modified: today.toJSON()
    };

    let external = {
        name: 'external',
        description: 'external users',
        created: today.toJSON(),
        modified: today.toJSON()
    };

    let bot = {
        name: 'bot',
        description: 'robots',
        created: today.toJSON(),
        modified: today.toJSON()
    };

    let model = app.models.user;

    model.create([
        {username: 'bot', email: 'example@example.com', password: 'test123'},
        {username: 'admin', email: 'example2@example.com', password: 'test123'},
        {username: 'iAdmin', email: 'example3@example.com', password: 'test123'},
        {username: 'eUser', email: 'example4@example.com', password: 'test123'},
    ], function(err, users) {
        if (err) throw err;

        app.models.Role.create(bot, function (err, botRole) {
            if (err) throw err;

            botRole.principals.create({principalType: app.models.RoleMapping.user, principalID: users[0].id}, function(err, principal) {
                if (err) throw err;
            });
        });

        app.models.Role.create(admin, function (err, adminRole) {
            if (err) throw err;

            adminRole.principals.create({principalType: app.models.RoleMapping.user, PrincipalID: users[1].id}, function(err, principal) {
                if (err) throw err;
            });
        });

        app.models.Role.create(admin, function (err, internalRole) {
            if (err) throw err;

            internalRole.principals.create({principalType: app.models.RoleMapping.user, PrincipalID: users[2].id}, function(err, principal) {
                if (err) throw err;
            });
        });

        app.models.Role.create(external, function (err, externalRole) {
            if (err) throw err;

            externalRole.principals.create({principalType: app.models.RoleMapping.user, PrincipalID: users[3].id}, function(err, principal) {
                if (err) throw err;
            });
        });
    });
};

角色和动态 roles/states($everyone 和 $authenticated)之间存在差异,而您的角色存储在 table 中以保持与用户 $everyone 和 $authenticated 的关联只是用户的一种状态。如果正确,请查看名为 "RoleMapping" 的 table。此外,如果您有自定义角色,请创建自定义 RoleResolver。

确实有很好的文档,在 Loopback 3 中入门真的不难。

https://loopback.io/doc/en/lb3/Defining-and-using-roles.html

这个例子让我对一般角色有了很好的理解:

https://github.com/strongloop/loopback-example-access-control/blob/master/server/boot/role-resolver.js

这是一个完整的项目,因此您也可以在那里查看模型。

你的两个 table 应该是这样的:

GET role -->> [table - role]

[
  {
    "roleId": 1,
    "name": "admin",
    "description": "admin",
    "created": "2016-08-23T16:46:07.572Z",
    "modified": "2016-08-23T16:46:07.572Z"
  },
  {
    "roleId": 2,
    "name": "internal",
    "description": "internal",
    "created": "2016-08-23T16:46:07.574Z",
    "modified": "2016-08-23T16:46:07.574Z"
  }
]


Get Role Mapping  [table- user-role]-->>

[
  {
    "userRoleId": 123,
    "roleId": 2, //id of role i.e. 1 for admin 
    "principalType": "USER",
    "principalId": "1234",
    "created": null,
    "modified": null
  },
  ..
  ...
]

所以通过查看您的代码,我可以说您没有将 roleId 添加到 roleMapping table。

首先添加角色table、

中的所有角色

现在创建用户并在角色映射中添加该用户的条目 table 并为其分配一个 roleID,请参阅上面的代码,其中 roleId 1 表示管理员角色。

实际上,您的代码存在一些语法和逻辑错误!

  1. app.models.RoleMapping.USER 而不是 app.models.RoleMapping.user(如@Farid 所说)。
  2. loopback acl 中没有"DELETE" accessType。您应该使用“*”、"READ"、"WRITE" 或 "EXECUTE" 作为 accesType 值。 "WRITE" 支持 "create"、"updateAttributes"、"upsert" 和 "destroyById" 资源。 (更多详情见 loopback documentation)。

更改 acl 如下代码:

"acls": [ { "accessType": "*", "principalType": "ROLE", "principalId": "$everyone", "permission": "DENY" }, { "accessType": "READ", "principalType": "ROLE", "principalId": "$authenticated", "permission": "ALLOW" }, { "accessType": "*", "principalType": "ROLE", "principalId": "admin", "permission": "ALLOW" }, { "principalType": "ROLE", "principalId": "internal", "permission": "ALLOW", "property": ["create", "updateAttributes", "upsert"] }, { "principalType": "ROLE", "principalId": "bot", "permission": "ALLOW", "property": ["create", "updateAttributes", "upsert"] } ]

  1. 最后,确保正确执行角色和角色映射。

我遇到的主要问题与以下项目有关:

  1. 使用 app.models.RoleMapping.USER 而不是 app.models.RoleMapping.user(早期在代码库中已更改)

  2. 使用principalId代替principalID

由于其他 ACL 因无法正常工作而在一段时间前已从应用程序中删除,我无法说明它们是否也导致了问题,但我会在过去添加它们确保为 LB3 使用正确的权限。