身份验证 #

服务器具有内置身份验证,因此客户端只有在拥有服务器密钥的情况下才能发送请求和进行连接。默认服务器密钥为defaultkey但有必要设置一个唯一值。这个值应该嵌入到客户端代码中。

身份验证成功后,客户端可以作为用户创建会话。

Client
1
2
var useSSL = false;
var client = new nakamajs.Client("defaultkey", "127.0.0.1", 7350, useSSL);
Client
1
2
// Use "https" scheme if you've setup SSL.
var client = new Client("http", "127.0.0.1", 7350, "defaultkey");
Client
1
2
3
4
5
NClientParameters parameters;
parameters.serverKey = "defaultkey";
parameters.host = "127.0.0.1";
parameters.port = DEFAULT_PORT;
NClientPtr client = createDefaultClient(parameters);
Client
1
2
3
Client client = new DefaultClient("defaultkey", "127.0.0.1", 7349, false)
// or same as above.
Client client = DefaultClient.defaults("defaultkey");
Client
1
onready var client := Nakama.create_client("defaultkey", "127.0.0.1", 7350, "http")
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
local defold = require "nakama.engine.defold"

local config = {}
config.host = 127.0.0.1
config.port = 7350
config.use_ssl = false
config.username = "defaultkey"
config.engine = defold

local client = nakama.create_client(config)

每个用户账户都是由用于身份验证的一个选项创建的。因为可以通过这些选项访问用户账户,我们将这些选项分别称为“链接”。您可以向每个帐户添加多个链接,这有助于用户在不同的设备上以多种方式登录。

验证身份 #

与服务器互动之前,您必须通过在系统中进行身份验证获取会话令牌。身份验证系统非常灵活。您可以使用电子邮箱注册用户,链接他们的Facebook帐户,并使用它在另一台设备上登录。

如果用于身份验证的标识符先前并不存在于系统中,则系统会默认自动创建用户。设备部分介绍了这种模式。

请在相关指南中查看关于在各个客户端处理注册和登录的最佳方式的完整示例。

设备 #

设备标识符可以用于在不引人注目的情况下在服务器中注册用户。这提供了流畅的用户体验,但可能不可靠,因为设备标识符有时会在设备更新中发生改变。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

设备标识符必须包含带破折号的字母数字字符,长度在10至128字节之间。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/device?create=true&username=mycustomusername" \
  --user 'defaultkey:' \
  --data '{"id":"uniqueidentifier"}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/authenticate/device?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "id": "uniqueidentifier"
}
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
// This import is only required with React Native
var deviceInfo = require('react-native-device-info');
var deviceId = null;

try {
  const value = await AsyncStorage.getItem('@MyApp:deviceKey');

  if (value !== null){
    deviceId = value
  }
  else {
    deviceId = deviceInfo.getUniqueID();

    AsyncStorage.setItem('@MyApp:deviceKey', deviceId).catch(function(error){
      console.log("An error occurred: %o", error);
    });
  }
}
catch (error) {
  console.log("An error occurred: %o", error);
}

var create = true;
const session = await client.authenticateDevice(deviceId, create, "mycustomusername");
console.info("Successfully authenticated:", session);
Client
1
2
3
4
// Should use a platform API to obtain a device identifier.
var deviceId = System.Guid.NewGuid().ToString();
var session = await client.AuthenticateDeviceAsync(deviceId);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
auto loginFailedCallback = [](const NError& error)
{
};

auto loginSucceededCallback = [](NSessionPtr session)
{
    cout << "Successfully authenticated" << endl;
};

std::string deviceId = "unique device id";

client->authenticateDevice(deviceId, opt::nullopt, opt::nullopt, {}, loginSucceededCallback, loginFailedCallback);
Client
1
2
3
String id = UUID.randomUUID().toString();
Session session = client.authenticateDevice(id).get();
System.out.format("Session: %s ", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
9
# Unique ID is not supported by Godot in HTML5, use a different way to generate an id, or a different authentication option.
var deviceid = OS.get_unique_id()
var session : NakamaSession = yield(client.authenticate_device_async(deviceid), "completed")

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

print("Successfully authenticated: %s" % session)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
-- login using the token and create an account if the user
-- doesn't already exist
local result = client.authenticate_device(defold,uuid(), nil, true, "mycustomusername")

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

在游戏中,使用GoogleGame Center以不引人注意的方式注册用户通常是更好的选择。

电子邮箱 #

可以使用电子邮箱和密码注册用户。在存储到数据库服务器之前对密码进行了哈希处理,管理员无法读取或“恢复”密码。这保护了用户的隐私。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

电子邮件地址必须是RFC-5322所定义的有效地址,密码必须至少包含8个字符。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/email?create=true&username=mycustomusername" \
  --user 'defaultkey:' \
  --data '{"email":"email@example.com", "password": "3bc8f72e95a9"}'
Client
1
2
3
4
5
6
7
8
9
POST /v2/account/authenticate/email?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "email": "email@example.com",
  "password": "3bc8f72e95a9"
}
Client
1
2
3
4
5
const email = "email@example.com";
const password = "3bc8f72e95a9";
const create = true;
const session = await client.authenticateEmail(email, password, create, "mycustomusername");
console.info("Successfully authenticated:", session);
Client
1
2
3
4
const string email = "email@example.com";
const string password = "3bc8f72e95a9";
var session = await client.AuthenticateEmailAsync(email, password);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
auto successCallback = [](NSessionPtr session)
{
    std::cout << "Authenticated successfully. User ID: " << session->getUserId() << std::endl;
};

auto errorCallback = [](const NError& error)
{
};

string email = "email@example.com";
string password = "3bc8f72e95a9";
string username = "mycustomusername";
bool create = true;
client->authenticateEmail(email, password, username, create, {}, successCallback, errorCallback);
Client
1
2
3
4
String email = "email@example.com";
String password = "3bc8f72e95a9";
Session session = client.authenticateEmail(email, password).get();
System.out.format("Session: %s ", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
9
var email = "email@example.com"
var password = "3bc8f72e95a9"
var session : NakamaSession = yield(client.authenticate_email_async(email, password, "mycustomusername", true), "completed")

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

print("Successfully authenticated: %s" % session)
Client
1
2
3
4
5
6
7
8
local result = client.authenticate_email("email@example.com", "3bc8f72e95a9", nil, true, "mycustomusername")

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

社交供应商 #

服务器支持通过许多不同的社交供应商注册和登录。所有供应商均从社交服务中提取用户帐户以用于设置用户。在某些情况下,也会将用户的好友提取并添加到好友列表中。

要使用任意供应商进行用户注册或登录,都必须从相应的社交服务中获取OAuth或访问令牌。

Apple #

请按照Apple开发人员文档将使用Apple注册集成到您的应用程序中。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/apple?create=true&username=mycustomusername" \
  --user 'defaultkey:' \
  --data '{"token":"..."}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/authenticate/apple?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "token": "...",
}
Client
1
2
3
4
5
const token = "...";
const create = true;
const username = "...";
const session = await client.authenticateApple(token, create, username);
console.info("Successfully authenticated: %o", session);
Client
1
2
3
4
5
var username = "...";
var token = "...";

var session = await client.AuthenticateAppleAsync(token, username);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
auto successCallback = [](NSessionPtr session)
{
    std::cout << "Authenticated successfully. User ID: " << session->getUserId() << std::endl;
};

auto errorCallback = [](const NError& error)
{
};

std::string username = "...";
std::string token = "...";

client->authenticateApple(token, username);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
var username = "..."
var token = "..."

var session : NakamaSession = yield(client.authenticate_apple_async(token, username), "completed")

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

print("Successfully authenticated: %s" % session)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- Use https://defold.com/assets/siwa/
local token = "..."
local username = "..."
local result = client.authenticate_apple(token, username)

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

Facebook #

要使用Facebook,您需要将Facebook SDK添加到您的项目中,您可以 在线下载。遵循关于如何集成代码的指南。对于移动项目,您还需要完成关于如何配置iOS和Android的说明。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

进行身份验证时,您可以选择将Facebook好友导入Nakama好友图谱中。为此,设置import为true。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/facebook?create=true&username=mycustomusername&import=true" \
    --user 'defaultkey:' \
    --data '{"token":"valid-oauth-token"}' # Supports the use of both OAuth and Facebook Limited Login (JWT) tokens.
Client
1
2
3
4
5
6
7
8
POST /v2/account/authenticate/facebook?create=true&username=mycustomusername&import=true
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "token": "...",
}
Client
1
2
3
4
const oauthToken = "...";
const import = true;
const session = await client.authenticateFacebook(oauthToken, true, "mycustomusername", import);
console.log("Successfully authenticated:", session);
Client
1
2
3
const string oauthToken = "...";
var session = await client.AuthenticateFacebookAsync(oauthToken);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
auto loginFailedCallback = [](const NError& error)
{
};

auto loginSucceededCallback = [](NSessionPtr session)
{
    cout << "Authenticated successfully. User ID: " << session->getUserId() << endl;
};

std::string oauthToken = "...";
bool importFriends = true;
client->authenticateFacebook(oauthToken, "mycustomusername", true, importFriends, {}, loginSucceededCallback, loginFailedCallback);
Client
1
2
3
String oauthToken = "...";
Session session = client.authenticateFacebook(oauthToken).get();
System.out.format("Session %s", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
var oauth_token = "..."
var session : NakamaSession = yield(client.authenticate_facebook_async(oauth_token), "completed")

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

print("Successfully authenticated: %s" % session)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
-- Use the official Defold Facebook integration (www.defold.com/extension-facebook)
local permissions = { "public_profile" }
-- login using read permissions
-- there is no need to specify a publishing audience when requesting read permissions
facebook.login_with_permissions(permissions, facebook.AUDIENCE_NONE, function(self, data)
  local result = client.authenticate_facebook(facebook.access_token(), nil, true, "mycustomusername")

  if not result.token then
    print("Unable to login")
    return
  end
  -- store the token and use it when communicating with the server
  client.set_bearer_token(result.token)
end)

即时Facebook #

确保您已经为Nakama配置了FB即时应用程序密钥,并使用FBInstant.initializeAsync()初始化了Facebook即时游戏SDK。

Code snippet for this language .NET/Unity has not been found. Please choose another language to show equivalent examples.
Code snippet for this language gdscript has not been found. Please choose another language to show equivalent examples.
Code snippet for this language Java/Android has not been found. Please choose another language to show equivalent examples.
Code snippet for this language C++/Unreal/Cocos2d-x has not been found. Please choose another language to show equivalent examples.
Code snippet for this language cURL has not been found. Please choose another language to show equivalent examples.

Client
1
2
3
const result = await FBInstant.player.getSignedPlayerInfoAsync();
var session = await client.authenticateFacebookInstantGame(result.getSignature());
console.info("Successfully authenticated: %o", session);
Client
1
2
3
4
5
6
7
8
var signed_player_info = "..."
var session : NakamaSession = yield(client.authenticate_facebook_instant_game_async(signed_player_info), "completed")

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

print("Successfully authenticated: %s" % session)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
-- Use the official Defold Facebook Instant Games integration (www.defold.com/extension-fbinstant)
fbinstant.get_signed_player_info("developer payload", function(self, signature)
  local result = client.authenticate_facebook_instant_game(signature, nil, true, "mycustomusername")

  if not result.token then
    print("Unable to login")
    return
  end
  -- store the token and use it when communicating with the server
  client.set_bearer_token(result.token)
end)

Google #

与通过Facebook注册和登录类似,您应该使用Google的一个客户端SDK。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/google?create=true&username=mycustomusername" \
  --user 'defaultkey:' \
  --data '{"token":"valid-oauth-token"}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/authenticate/google?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "token": "...",
}
Client
1
2
3
4
const playerIdToken = "...";
const create = true;
const session = await client.authenticateGoogle(oauthToken, create, "mycustomusername");
console.info("Successfully authenticated: %o", session);
Client
1
2
3
const string playerIdToken = "...";
var session = await client.AuthenticateGoogleAsync(playerIdToken);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
auto successCallback = [](NSessionPtr session)
{
    std::cout << "Authenticated successfully. User ID: " << session->getUserId() << std::endl;
};

auto errorCallback = [](const NError& error)
{
};

string oauthToken = "...";
client->authenticateGoogle(oauthToken, "mycustomusername", true, {}, successCallback, errorCallback);
Client
1
2
3
String playerIdToken = "...";
Session session = client.authenticateGoogle(oauthToken).get();
System.out.format("Session %s", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
var oauth_token = "..."
var session : NakamaSession = yield(client.authenticate_google_async(oauth_token), "completed")

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

print("Successfully authenticated: %s" % session)
Client
1
2
3
4
5
6
7
8
local result = client.authenticate_google(oauth_token, nil, true, "mycustomusername")

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

Game Center #

Apple设备具有内置的身份验证,可以通过Game Center在不进行用户互动的情况下完成身份验证。由于Apple服务的运作方式,注册或登录过程有些复杂。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

Code snippet for this language JavaScript/Cocos2d-js has not been found. Please choose another language to show equivalent examples.
Code snippet for this language Java/Android has not been found. Please choose another language to show equivalent examples.

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/gamecenter?create=true&username=mycustomusername" \
  --user 'defaultkey:' \
  --data '{"player_id":"...", "bundle_id":"...", "timestamp_seconds":0, "salt":"...", "public_key_url":"..."}'
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
POST /v2/account/authenticate/gamecenter?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "player_id": "...",
  "bundle_id": "...",
  "timestamp_seconds": 0,
  "salt": "...",
  "signature": "...",
  "public_key_url": "..."
}
Client
1
2
3
4
5
6
7
8
9
var bundleId = "...";
var playerId = "...";
var publicKeyUrl = "...";
var salt = "...";
var signature = "...";
var timestamp = "...";
var session = await client.AuthenticateGameCenterAsync(bundleId, playerId,
    publicKeyUrl, salt, signature, timestamp);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
auto successCallback = [](NSessionPtr session)
{
    std::cout << "Authenticated successfully. User ID: " << session->getUserId() << std::endl;
};

auto errorCallback = [](const NError& error)
{
};

std::string playerId = "...";
std::string    bundleId = "...";
NTimestamp timestampSeconds = "...";
std::string salt = "...";
std::string signature = "...";
std::string publicKeyUrl = "...";

client->authenticateGameCenter(playerId, bundleId, timestampSeconds, salt, signature, publicKeyUrl, "mycustomusername", true, {}, successCallback, errorCallback);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var bundle_id = "..."
var player_id = "..."
var public_key_url = "..."
var salt = "..."
var signature = "..."
var timestamp = "..."
var session : NakamaSession = yield(client.authenticate_game_center_async(bundle_id, player_id, public_key_url, salt, signature, timestamp), "completed")

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

print("Successfully authenticated: %s" % session)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
-- Use https://defold.com/assets/gamekit/
local bundle_id = "..."
local player_id = "..."
local public_key_url = "..."
local salt = "..."
local signature = "..."
local timestamp_seconds = 0
local result = client.authenticate_game_center(bundle_id, player_id, public_key_url, salt, signature, timestamp_seconds, nil, true, "mycustomusername")

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

Steam #

Steam要求您在注册用户之前配置服务器。查看配置部分,了解您需要对服务器进行哪些设置。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

进行身份验证时,您可以选择将Steam好友导入Nakama好友图谱中。为此,设置import为true。

Code snippet for this language JavaScript/Cocos2d-js has not been found. Please choose another language to show equivalent examples.
Code snippet for this language JavaScript/Cocos2d-js has not been found. Please choose another language to show equivalent examples.
Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/steam?create=true&username=mycustomusername&import=true" \
  --user 'defaultkey:' \
  --data '{"token":"valid-steam-token"}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/authenticate/steam?create=true&username=mycustomusername&import=true
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "token": "...",
}
Client
1
2
3
4
5
6
const token = "...";
const create = true;
const username = "...";
const sync = true;
const session = await client.authenticateSteam(token, create, username, sync);
console.info("Successfully authenticated: %o", session);
Client
1
2
3
4
const string token = "...";
const bool importFriends = true;
var session = await client.AuthenticateSteamAsync(token, importFriends);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
auto successCallback = [](NSessionPtr session)
{
    std::cout << "Authenticated successfully. User ID: " << session->getUserId() << std::endl;
};

auto errorCallback = [](const NError& error)
{
};

string token = "...";
string username = "mycustomusername";
bool create = true;
bool importFriends = true;
client->authenticateSteam(token, username, create, importFriends, {}, successCallback, errorCallback);
Client
1
2
3
4
String token = "...";
Bool importFriends = true;
Session session = client.authenticateSteam(token, importFriends).get();
System.out.format("Session %s", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
9
var steam_token = "..."
var import_friends = true
var session : NakamaSession = yield(client.authenticate_steam_async(steam_token, import_friends), "completed")

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

print("Successfully authenticated: %s" % session)
Client
1
2
3
4
5
6
7
8
9
-- Use https://defold.com/assets/steamworks/
local result = client.authenticate_steam(steam_token, nil, true, "mycustomusername")

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

自定义 #

可通过与使用设备标识符类似的方式使用自定义标识符登录或注册用户。如果您要使用外部或自定义用户标识服务,应使用此选项。例如,EA的Origin服务处理拥有自己的用户ID的账户。

自定义标识符必须包含带破折号的字母数字字符,长度在6至128字节之间。

创建帐户时,您可选择自定义用户名。为此,请设置username为一个自定义名称。如果您仅想验证身份而不会暗中创建用户账户,请设置create为false。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/custom?create=true&username=mycustomusername" \
  --user 'defaultkey:' \
  --data '{"id":"some-custom-id"}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/authenticate/custom?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "id": "some-custom-id",
}
Client
1
2
3
4
const customId = "some-custom-id";
const create = true;
const session = await client.authenticateCustom(customId, create, "mycustomusername");
console.info("Successfully authenticated:", session);
Client
1
2
3
const string customId = "some-custom-id";
var session = await client.AuthenticateCustomAsync(customId);
System.Console.WriteLine("New user: {0}, {1}", session.Created, session);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
auto successCallback = [](NSessionPtr session)
{
    std::cout << "Authenticated successfully. User ID: " << session->getUserId() << std::endl;
};

auto errorCallback = [](const NError& error)
{
};

string id = "some-custom-id";
string username = "mycustomusername";
bool create = true;
client->authenticateCustom(id, username, create, {}, successCallback, errorCallback);
Client
1
2
3
String customId = "some-custom-id";
Session session = client.authenticateCustom(customId).get();
System.out.format("Session %s", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
var custom_id = "some-custom-id"
var session : NakamaSession = yield(client.authenticate_custom_async(custom_id), "completed")

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

print("Successfully authenticated: %s" % session)
Client
1
2
3
4
5
6
7
8
local result = client.authenticate_custom(custom_id, nil, true, "mycustomusername")

if not result.token then
  print("Unable to login")
end

-- store the token and use it when communicating with the server
client.set_bearer_token(result.token)

会话 #

身份验证调用成功时,服务器会使用会话对象进行响应。会话对象至少包含以下内容:

  • 用户ID
  • 用户名
  • 缓存在令牌中的一组变量
  • 创建时间
  • 到期时间

客户端获得会话对象后,您就可以利用Nakama的实时特性,例如多人游戏, 通知状态更新传递流数据实时聊天

Client
1
2
3
var socket = client.createSocket();
session = await socket.connect(session);
console.info("Socket connected.");
Client
1
2
3
var socket = Socket.From(client);
await socket.ConnectAsync(session);
System.Console.WriteLine("Socket connected.");
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
int port = 7350; // different port to the main API port
bool createStatus = true; // if the server should show the user as online to others.
// define real-time client in your class as NRtClientPtr rtClient;
rtClient = client->createRtClient(port);
// define listener in your class as NRtDefaultClientListener listener;
listener.setConnectCallback([]()
{
    cout << "Socket connected." << endl;
});

rtClient->setListener(&listener);
rtClient->connect(session, createStatus);
Client
1
2
SocketClient socket = client.createSocket();
socket.connect(session, new AbstractSocketListener() {}).get();
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Make this a node variable, or it will disconnect when the function that creates it returns.
onready var socket := Nakama.create_socket_from(client)

func _ready():
    var connected : NakamaAsyncResult = yield(socket.connect_async(session), "completed")

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

    print("Socket connected.")
Client
1
2
3
4
5
6
local socket = client.create_socket()
local ok, err = socket.connect()

if not ok then
  print("Unable to connect: ", err)
end

链接或取消链接 #

您可以将一个或多个其他登录选项链接到当前用户。这样就可以轻松支持每个用户的多次登录,并在不同的设备上轻松识别一个用户。

您只能链接尚未与其他用户帐户一起使用的设备ID、自定义ID和社交供应商ID。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/link/custom" \
  --header 'Authorization: Bearer $session' \
  --data '{"id":"some-custom-id"}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/link/custom
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
{
  "id":"some-custom-id"
}
Client
1
2
3
const customId = "some-custom-id";
const success = await client.linkCustom(session, customId);
console.log("Successfully linked custom ID to current user.");
Client
1
2
3
const string customId = "some-custom-id";
await client.LinkCustomAsync(session, customId);
System.Console.WriteLine("Id '{0}' linked for user '{1}'", customId, session.UserId);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
auto linkFailedCallback = [](const NError& error)
{
};

auto linkSucceededCallback = []()
{
    cout << "Linked successfully" << endl;
};

std::string customid = "some-custom-id";

client->linkCustom(customid, linkSucceededCallback, linkFailedCallback);
Client
1
2
3
String customId = "some-custom-id";
client.linkCustom(session, customId).get();
System.out.format("Id %s linked for user %s", customId, session.getUserId());
Client
1
2
3
4
5
6
7
8
var custom_id = "some-custom-id"
var linked : NakamaAsyncResult = yield(client.link_custom_async(session, custom_id), "completed")

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

print("Id '%s' linked for user '%s'" % [custom_id, session.user_id])
Client
1
2
3
4
5
local result = client.link_custom(custom_id)

if result.error then
  print("An error occurred:", result.error)
end

您可以为当前用户的任何链接登录选项取消链接。

Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/unlink/custom" \
  --header 'Authorization: Bearer $session' \
  --data '{"id":"some-custom-id"}'
Client
1
2
3
4
5
6
7
8
POST /v2/account/unlink/custom
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
{
  "id":"some-custom-id"
}
Client
1
2
3
const customId = "some-custom-id";
const success = await client.unlinkCustom(session, customId);
console.info("Successfully unlinked custom ID from the current user.");
Client
1
2
3
const string customId = "some-custom-id";
await client.UnlinkCustomAsync(session, customId);
System.Console.WriteLine("Id '{0}' unlinked for user '{1}'", customId, session.UserId);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
auto unlinkFailedCallback = [](const NError& error)
{
};

auto unlinkSucceededCallback = []()
{
    cout << "Successfully unlinked custom ID from the current user." << endl;
};

std::string customid = "some-custom-id";

client->unlinkCustom(customid, unlinkSucceededCallback, unlinkFailedCallback);
Client
1
2
3
String customId = "some-custom-id";
client.unlinkCustom(session, customId).get();
System.out.format("Id %s unlinked for user %s", customId, session.getUserId());
Client
1
2
3
4
5
6
7
8
var custom_id = "some-custom-id"
var unlinked : NakamaAsyncResult = yield(client.unlink_custom_async(session, custom_id), "completed")

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

print("Id '%s' unlinked for user '%s'" % [custom_id, session.user_id])
Client
1
2
3
4
5
local result = client.unlink_custom(custom_id)

if result.error then
  print("An error occurred:", result.error)
end

您可以链接或取消链接许多不同的账户选项。

链接描述
AppleApple账户。
自定义来自其他标识服务的自定义标识符。
设备用户拥有的设备的唯一标识符。
电子邮箱用户设置的电子邮箱和密码。
FacebookFacebook社交账户。您可以选择在链接时导入Facebook好友。
Game Center来自Apple Game Center服务的账户。
GoogleGoogle账户。
Steam来自Steam网络的账户。