세션 #

일반적으로 “세션"은 사용자가 시스템에서 인증되는 기간입니다.

Nakama에서 세션은 서버 함수에 액세스할 때 클라이언트가 인증되었음을 증명하는 클라이언트 측 객체로 표시됩니다.

세션 기간은 구성에서 token_expiry_sec 속성으로 설정할 수 있습니다. 세션 기간은 게임의 평균 플레이 세션 길이의 약 2~3배로 설정하는 것이 좋습니다.

세션은 이 설정 기간이 지나면 만료되어 무효화됩니다. 클라이언트가 인증할 때 새로 고침 토큰이 제공되므로 새로 고침 토큰이 유효한 동안 새 인증 토큰을 얻을 수 있습니다. 새로 고침 토큰이 만료된 경우 새 세션을 가져오려면 서버에 다시 인증해야 합니다.

세션 세부정보 #

다음 코드를 사용하여 사용자의 ID, 이름 및 세션 만료 여부에 액세스할 수 있습니다:

Code snippet for this language cURL has not been found. Please choose another language to show equivalent examples.
Code snippet for this language REST 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.
Code snippet for this language REST has not been found. Please choose another language to show equivalent examples.

Client
1
2
3
4
const id = "3e70fd52-7192-11e7-9766-cb3ce5609916";
const session = await client.authenticateDevice(id)
console.info("id:", session.user_id, "username:", session.username);
console.info("Session expired?", session.isexpired(Date.now() / 1000));
Client
1
2
3
4
const string id = "3e70fd52-7192-11e7-9766-cb3ce5609916";
var session = await client.AuthenticateDeviceAsync(id);
System.Console.WriteLine("Id '{0}' Username '{1}'", session.UserId, session.Username);
System.Console.WriteLine("Session expired? {0}", session.IsExpired);
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
auto loginFailedCallback = [](const NError& error)
{
};

auto loginSucceededCallback = [](NSessionPtr session)
{
    cout << "id " << session->getUserId() << " username " << session->getUsername() << endl;
    cout << "Session expired? " << (session->isExpired() ? "yes" : "no") << endl;
};

std::string deviceId = "3e70fd52-7192-11e7-9766-cb3ce5609916";

client->authenticateDevice(deviceId, opt::nullopt, opt::nullopt, {}, loginSucceededCallback, loginFailedCallback);
Client
1
2
3
var deviceid = SystemInfo.deviceUniqueIdentifier;
Session session = client.authenticateDevice(deviceid).get();
System.out.format("Session %s", session.getAuthToken());
Client
1
2
3
4
5
6
7
8
var session : NakamaSession = yield(client.authenticate_device_async(deviceid), "completed")

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

print("Id '%s' Username '%s'" % [session.id, session.username])
print("Session expired? %s" % session.expired)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
local result = client.authenticate_device(defold.uuid())

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

print(("Id '%s' Username '%s' "):format(result.user_id, result.username))

if os.time() > result.expires then
  print("Session has expired")
end

세션 새로 고침 #

Code snippet for this language cURL 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
client->authenticateRefresh(session);
Client
1
client.session_refresh(session.refresh_token)
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
POST /v2/session/refresh/
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "token": "<Refresh token>",
  "vars": {
    "key": "value",
    "key2": "value2"
  }
}
Client
1
session = yield(client.session_refresh_async(session), "completed)
Client
1
session = await client.sessionRefresh(session);
Client
1
session = await client.SessionRefreshAsync(session);

세션을 새로 고칠 때 선택적으로 새 세션 변수 값을 제공할 수 있습니다. 이러한 새 값이 현재 세션 객체에 저장된 모든 세션 변수 대신 사용됩니다.

세션 로그아웃 #

사용자가 활성 세션에서 로그아웃할 수 있도록 만드는 것은 좋은 보안 사례입니다. 예를 들어 이는 공유 장치를 사용할 때 다른 사람의 무단 액세스를 방지하는 데 사용할 수 있습니다.

Code snippet for this language cURL 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 C++/Unreal/Cocos2d-x 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 Defold 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.
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 Java/Android has not been found. Please choose another language to show equivalent examples.

Client
1
client.session_logout(session.refresh_token, session.token)
Client
1
2
3
4
5
6
7
8
9
POST /v2/session/logout/
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Basic base64(ServerKey:)
{
  "token": "<Session token to log out>",
  "refreshToken": "<Refresh token to invalidate>"
}
Client
1
yield(client.session_logout_async(session), "completed")
Client
1
await client.sessionLogout(session);
Client
1
await client.SessionLogoutAsync(session);

사용자 세션에서 로그아웃하면 인증 및 새로 고침 토큰이 무효화되지만 열려 있는 소켓 연결은 끊어지지 않습니다. 이것은 서버 측 sessionDisconnect 함수를 통해 수행할 수 있습니다. 해당 함수 참조를 확인하세요.

세션 변수 #

세션 변수를 사용하면 클라이언트 및 서버 측 코드가 게임 서버에서 생성된 세션 토큰에 추가 키/값 쌍을 포함시킬 수 있습니다. 이렇게 하면 세션 토큰이 에지 캐시 역할을 할 수 있으며 세션이 활성 상태로 유지되는 한 해당 정보를 사용할 수 있습니다.

이는 분석, 추천 보너스 또는 보상 프로그램과 같은 다양한 기능과 도구를 구현하는 데 사용할 수 있습니다.

세션을 새로 고칠 때 선택적으로 새 세션 변수 값을 제공할 수 있습니다. 이러한 새 값이 현재 세션 객체에 저장된 모든 세션 변수 대신 사용됩니다.

클라이언트에서 설정 #

클라이언트의 인증 요청에 변수를 설정하려면 다음을 사용합니다:

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 Java/Android 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.

Client
1
2
3
local vars = { key = "value" }
local create = true
local result = client.authenticate_email(email, password, vars, create, "mycustomusername")
Client
1
2
3
4
5
Map<String, String> vars = new HashMap<>();
vars.put("Key", "Value");
vars.put("Key2", "Value2");

Session session = client.authenticateEmail("<email>", "<password>", vars).get();
Client
1
2
3
4
5
6
7
var vars = {
    "key" : "value",
    "key2" : "value2"
    # ...
}

var session : NakamaSession = yield(client.authenticate_email_async("<email>", "<password>", null, true, vars), "completed")
Client
1
2
3
4
5
var vars = new Dictionary<string, string>();
vars["key"] = "value";
vars["key2"] = "value2";
// ...
var session = await client.AuthenticateEmailAsync("<email>", "<password>", null, true, vars);
Client
1
2
3
const create = true;
const session = await client.authenticateEmail(email, password, create, "mycustomusername", {key: "value"});
console.info("Successfully authenticated:", session);
Client
1
2
3
curl "http://127.0.0.1:7350/v2/account/authenticate/email?create=true&username=mycustomusername" \
--user 'defaultkey:' \
--data '{"email": "hello@heroiclabs.com", "password": "password", "vars": { "key": "value" }}'
Client
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
POST /v2/account/authenticate/email?create=true&username=mycustomusername
Host: 127.0.0.1:7350
Accept: application/json
Content-Type: application/json
Authorization: Bearer <session token>
{
    "email": "hello@heroiclabs.com",
    "password": "password",
    "vars": {
        "key": "value"
    }
}

이 예는 이메일 인증으로 세션 변수를 설정하는 것을 보여주지만 이 기능은 다른 모든 인증 옵션과 모든 클라이언트 라이브러리에서 사용할 수 있습니다.

서버에서 설정 #

세션 변수는 서버에서 설정할 수 있지만 인증 후크 __이전__에만 가능합니다.

Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
local nk = require("nakama")

local function set_session_vars(context, payload)
  nk.logger_info("User session contains key-value pairs set by the client: " .. nk.json_encode(payload.account.vars))

  payload.account.vars["key_added_in_lua"] = "value_added_in_lua"
  return payload
end

nk.register_req_before(set_session_vars, "AuthenticateEmail")
Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error {
    if err := initializer.RegisterBeforeAuthenticateEmail(SetSessionVars); err != nil {
        logger.Error("Unable to register: %v", err)
        return err
    }

    return nil
}

func SetSessionVars(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, in *api.AuthenticateEmailRequest) (*api.AuthenticateEmailRequest, error) {
    logger.Info("User session contains key-value pairs set the client: %v", in.GetAccount().Vars)

    if in.GetAccount().Vars == nil {
        in.GetAccount().Vars = map[string]string{}
    }

    in.GetAccount().Vars["key_added_in_go"] = "value_added_in_go"

    return in, nil
}
Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let setSessionVars: nkruntime.BeforeHookFunction<nkruntime.AuthenticateEmailRequest> = function (context: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, payload: nkruntime.AuthenticateEmailRequest) {
  payload.account.vars = {
    key: 'key',
    value: 'value',
  }

  return payload;
}

function InitModule(ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, initializer: nkruntime.Initializer) {
  initializer.registerBeforeAuthenticateEmail(setSessionVars);
}

서버로 접속 #

일단 설정되면 세션 변수는 읽기 전용이 되며 모든 서버 후크에서 액세스할 수 있습니다. 세션 변수를 변경하거나 삭제하는 유일한 방법은 클라이언트가 다시 인증하도록 만드는 것입니다.

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
8
9
local nk = require("nakama")

local function access_session_vars(context, payload)
  nk.logger_info("User session contains key-value pairs set by both the client and the before authentication hook: " .. nk.json_encode(context.vars))

  return payload
end

nk.register_req_before(access_session_vars, "GetAccount")
Server
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
func InitModule(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, initializer runtime.Initializer) error {
    if err := initializer.RegisterBeforeGetAccount(AccessSessionVars); err != nil {
        logger.Error("Unable to register: %v", err)
        return err
    }

    return nil
}

func AccessSessionVars(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule) error {
    vars, ok := ctx.Value(runtime.RUNTIME_CTX_VARS).(map[string]string)

    if !ok {
        logger.Info("User session does not contain any key-value pairs set")
        return nil
    }

    logger.Info("User session contains key-value pairs set by both the client and the before authentication hook: %v", vars)
    return nil
}

Related Pages