访问控制 #

存储引擎有两个控制对象访问的功能。对象所有权和访问权限。

对象所有权 #

每个存储对象创建时都有一个所有者。所有者可以是创建对象的用户、系统所有者,也可以是使用代码运行库创建对象时指定的所有者。

从代码运行库写入对象时,除非明确设置,否则将系统用户视为所有者。默认将从客户端写入存储对象的用户设置为所有者。

系统所拥有的对象由系统用户创建,在服务器中以 nil UUID (00000000-0000-0000-0000-000000000000) 表示。系统所拥有的对象必须具有公开读取访问权限,客户端才能获取它。

这些代码示例显示如何检索系统所拥有的对象(标记为公开读取)。

Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
curl -X POST "http://127.0.0.1:7350/v2/storage" \
  -H 'Authorization: Bearer <session token>' \
  -d '{
    "object_ids": [
      {
        "collection": "configuration",
        "key": "config",
      }
    ]
  }'
Client
1
2
3
4
5
6
7
const objects = await client.readStorageObjects(session, {
  "object_ids": [{
    "collection": "configurations",
    "key": "config"
  }]
});
console.info("Read objects: %o", objects);
Client
1
2
3
4
5
6
var result = await client.ReadStorageObjectsAsync(session, new StorageObjectId {
    Collection = "configuration",
    Key = "config"
});

Console.WriteLine("Read objects: [{0}]", string.Join(",\n  ", result.Objects));
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
auto successCallback = [](const NStorageObjects& objects)
{
  for (auto& object : objects)
    {
        std::cout << "Object key: " << object.key << ", value: " << object.value << std::endl;
    }
};

std::vector<NReadStorageObjectId> objectIds;
NReadStorageObjectId objectId;
objectId.collection = "configurations";
objectId.key = "config";
objectIds.push_back(objectId);
client->readStorageObjects(session, objectIds, successCallback);
Client
1
2
3
4
StorageObjectId objectId = new StorageObjectId("configuration");
objectId.setKey("config");
StorageObjects objects = client.readStorageObjects(session, objectId).get();
System.out.format("Read objects %s", objects.getObjectsList().toString());
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var result : NakamaAPI.ApiStorageObjects = yield(client.read_storage_objects_async(session, [
    NakamaStorageObjectId.new("configuration", "config")
]), "completed")

if result.is_exception():
    print("An error occurred: %s" % result)
    return

print("Read objects:")

for o in result.objects:
    print("%s" % o)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
POST /v2/storage
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
{
  "object_ids": [
    {
      "collection": "configuration",
      "key": "config"
    }
  ]
}
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
local objects_ids = {
  {
				collection = "configuration",
				key = "config"
  }
}

local result = client.read_storage_objects(objects_ids)

if result.error then
  print(result.message)
  return
end

for _,object in ipairs(result.objects) do
  pprint(object)
end

您也可以使用代码运行库获取对象。代码运行库不受访问权限的相关标准规则的限制,因为服务器将其作为权威代码运行。

Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
local object_ids = {
  { collection = "configuration", key = "config", user_id = nil },
}

local objects = nk.storage_read(object_ids)

for _, o in ipairs(objects) do
  local message = ("value: %q"):format(o.value)
  nk.logger_info(message)
end
Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
objectIds := []*runtime.StorageRead{
    &runtime.StorageRead{
        Collection: "configuration",
        Key: "config",
    },
}

objects, err := nk.StorageRead(ctx, objectIds)

if err != nil {
    // Handle error.
} else {
    for _, object := range objects {
        logger.Info("value: %s", object.Value)
    }
}
Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
let objectIds: nkruntime.StorageReadRequest[] = [
  { collection: 'configuration', key: 'config', userId: '<uuid>' },
]

let objects: nkruntime.StorageObject[] = [];

try {
  let objects = nk.storageRead(objectIds);
} catch (error) {
  // Handle error
}

objects.forEach(function (o) {
  logger.info('value: %q', o.value);
});

对象权限 #

对象有权限,在写入或更新对象时,为此对象的所有者执行这些权限。

  • ReadPermission 可以为 Public Read (2)、Owner Read (1) 或 No Read (0)。
  • WritePermission 可以为 Owner Write (1) 或 No Write (0)。

当通过代码运行库与存储引擎交互时,这些权限将被忽略,因为服务器是权威的,始终可以读取/写入对象。因此,No Read / No Write 权限意味着没有客户端可以读取/写入此对象。

只有作为所有者的用户才能访问或修改具有 Owner ReadOwner Write 权限的对象。其他客户端不能访问此对象。

Public Read 意味着任何用户均可读取该对象。这对于用户需要与其他用户分享其游戏状态或组成部分的游戏玩法很实用。例如,有些具有自己的 "Army" 对象的用户想要互相战斗。每个用户都可以写入自己的公开读取对象,其他用户也可以读取该对象,以便在其他用户的设备上呈现该对象。

在从客户端修改对象时,对象的默认权限设置为 Owner ReadOwner Write。 在从运行库修改对象时,对象的默认权限设置为 No ReadNo Write。 在列出对象时,将仅返回具有合适权限的对象。

Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# "2" refers to Public Read permission
# "1" refers to Owner Write permission
curl -X PUT "http://127.0.0.1:7350/v2/storage" \
  -H 'Authorization: Bearer <session token>' \
  -d '{
    "objects": [
      {
        "collection": "battle",
        "key": "army",
        "value": "{"soldiers": 50}",
        "permission_read": 2,
        "permission_write": 1
      }
    ]
  }'
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
var army_setup = { "soldiers": 50 };
// "2" refers to Public Read permission
// "1" refers to Owner Write permission
const object_ids = await client.writeStorageObjects(session, [
  {
    "collection": "saves",
    "key": "savegame",
    "value": army_setup,
    "permission_read": 2,
    "permission_write": 1
  }
]);

console.info("Stored objects: %o", object_ids);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var armySetup = "{ "soldiers": 50 }";
// "2" refers to Public Read permission
// "1" refers to Owner Write permission
var result = await client.WriteStorageObjectsAsync(session, new WriteStorageObject
{
    Collection = "saves",
    Key = "savegame",
    Value = armySetup,
    PermissionRead = 2,
    PermissionWrite = 1
});

Console.WriteLine("Stored objects: [{0}]", string.Join(",\n  ", result.Objects));
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
auto successCallback = [](const NStorageObjectAcks& acks)
{
};

std::vector<NStorageObjectWrite> objects;
NStorageObjectWrite object;
object.collection = "saves";
object.key = "savegame";
object.value = "{ "soldiers": 50 }";
object.permissionRead = NStoragePermissionRead::PUBLIC_READ;   // Public Read permission
object.permissionWrite = NStoragePermissionWrite::OWNER_WRITE; // Owner Write permission
objects.push_back(object);
client->writeStorageObjects(session, objects, successCallback);
Client
1
2
3
4
String armySetup = "{ "soldiers": 50 }";
StorageObjectWrite object = new StorageObjectWrite("saves", "savegame", armySetup, PermissionRead.PUBLIC_READ, PermissionWrite.OWNER_WRITE);
StorageObjectAcks acks = client.writeStorageObjects(session, object).get();
System.out.format("Stored objects %s", acks.getAcksList());
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
var army_setup = "{ "soldiers": 50 }";
# "2" refers to Public Read permission
# "1" refers to Owner Write permission
var acks : NakamaAPI.ApiStorageObjectAcks = yield(client.write_storage_objects_async(session, [
    NakamaWriteStorageObject.new("saves", "savegame", 2, 1, army_setup, "")
]), "completed")

if acks.is_exception():
    print("An error occurred: %s" % acks)
    return

print("Stored objects: %s" % [acks.acks])
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
PUT /v2/storage
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
{
  "objects": [
    {
      "collection": "battle",
      "key": "army",
      "value": "{ "soldiers": 50 }",
      "permission_read": 2,
      "permission_write": 1
    }
  ]
}
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
local army_setup = json.encode({ soldiers = 50 })
local can_read = 2
local can_write = 1

local objects = {
  {
    collection = "battle",
    key = "army",
    permissionRead = can_read,
    permissionWrite = can_write,
    value = army_setup,
    version = version
  }
}

local result = client.write_storage_objects(objects)

if result.error then
  print(result.message)
  return
end

for _,ack in ipairs(result.acks) do
  pprint(ack)
end

您可以从代码运行库存储具有自定义权限的对象。

Code snippet for this language TypeScript has not been found. Please choose another language to show equivalent examples.
Server
1
2
3
4
5
6
7
local user_id = "4ec4f126-3f9d-11e7-84ef-b7c182b36521" -- Some user ID.

local new_objects = {
  { collection = "battle", key = "army", user_id = user_id, value = {}, permission_read = 2, permission_write = 1 }
}

nk.storage_write(new_objects)
Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
userID := "4ec4f126-3f9d-11e7-84ef-b7c182b36521" // Some user ID.
objects := []*runtime.StorageWrite{
    &runtime.StorageWrite{
        Collection:      "battle",
        Key:             "army",
        UserID:          userID,
        Value:           "{}",
        PermissionRead:  2,
        PermissionWrite: 1,
    },
}

if _, err := nk.StorageWrite(ctx, objects); err != nil {
    // Handle error.
}

Related Pages