Defining and using roles(定义和使用 角色)

  • 静态角色
  • 动态角色

Loopback 允许使用定义 静态 和 动态角色
区别:

  • 静态角色被存储在一个数据源中,同时映射到用户上
  • 没有确定在哪里赋予用户角色

Static roles

下面代码段,展示如何 定义一个新的静态角色 并 分配用户给该角色

  1. // 创建用户
  2. User.create([
  3. {username: 'John', email: 'john@doe.com', password: 'opensesame'},
  4. {username: 'Jane', email: 'jane@doe.com', password: 'opensesame'},
  5. {username: 'Bob', email: 'bob@projects.com', password: 'opensesame'}
  6. ], function(err, users) {
  7. if (err) return cb(err);
  8. // 创建角色, 设置 role 的 name 属性
  9. Role.create({
  10. name: 'admin'
  11. }, function(err, role) {
  12. if (err) cb(err);
  13. // 绑定 Bob 成为 role 角色
  14. role.principals.create({
  15. principalType: RoleMapping.USER,
  16. principalId: users[2].id
  17. }, function(err, principal) {
  18. cb(err);
  19. });
  20. });
  21. });

然后可以使用访问控制上面定义的角色:

  1. {
  2. "accessType": "EXECUTE",
  3. "principalType": "ROLE",
  4. "principalId": "admin",
  5. "permission": "ALLOW",
  6. "property": "find"
  7. }

Dynamic roles

有时候,静态角色不够灵活, Loopback 允许定义 动态属性 在运行时.

Loopback 提供了一下 内置的动态角色:

Role object property(角色对象属性) 字符串值 描述
Role.OWNER $owner 对象所有者
Role.AUTHENTICATED $authenticated 认证用户
Role.UNAUTHENTICATED $unauthenticated 未认证用户
Role.EVERYONE $everyone 任何用户

使用 $owner时, 目标模型需要有一个关系的 belongsTo 到 User Model(或者其他继承 user 的 model),
同时 属性疲惫到 目标模型对象实例的一个外键. $owner 检查只有 :id 的 remote 方法 ?

使用 Role.registerResolver() 注册一个 自定义角色,在 引导脚本中, 这个方法需要两个参数:

  1. 第一个参数: 角色名字符串
  2. 第二个参数: function 确定主要是在指定的作用, function(role, context, callback)

Demo

  1. // 在 bootScript 中
  2. module.exports = function(app) {
  3. // 获取 Role 的 model
  4. var Role = app.models.Role;
  5. // 注册名为 teamMember 的橘色名,并设置逻辑
  6. // role 新注册的 teamMember 的实例
  7. // 上下文, 回调函数 cb , cb(err, false) 为失败, 为 cb(null, true) 为通过
  8. Role.registerResolver('teamMember', function(role, context, cb) {
  9. /**
  10. * rejest 认证失败调用方法
  11. * @param err
  12. */
  13. function reject(err) {
  14. if(err) {
  15. return cb(err);
  16. }
  17. cb(null, false);
  18. }
  19. // 角色只真对 project Model
  20. if (context.modelName !== 'project') {
  21. return reject();
  22. }
  23. // 只能是登录用户
  24. var userId = context.accessToken.userId;
  25. if (!userId) {
  26. return reject(); // do not allow anonymous users
  27. }
  28. // 查找项目id
  29. context.model.findById(context.modelId, function(err, project) {
  30. // 没找到项目, 权限失败
  31. if(err || !project) {
  32. reject(err);
  33. }
  34. // 获取 Team
  35. var Team = app.models.Team;
  36. // 查询先关 team 和 user 的关联是否建立
  37. Team.count({
  38. ownerId: project.ownerId,
  39. memberId: userId
  40. }, function(err, count) {
  41. if (err) {
  42. return reject(err);
  43. }
  44. cb(null, count > 0); // true = is a team member
  45. });
  46. });
  47. });
  48. };

使用以上方法定义角色后,我们可以限制是该项目的团队成员的用户的项目信息的访问.

  1. {
  2. "accessType": "READ",
  3. "principalType": "ROLE",
  4. "principalId": "teamMember",
  5. "permission": "ALLOW",
  6. "property": "findById"
  7. }