跳转到主要内容

会话保持及重复登录检测

定期向服务器发送会话保持信号,并检查是否有其他设备重复登录的 API。

示例代码说明

本文档的示例代码仅供参考。使用 Update() 的回调调用方式会在每帧进行检查,因此在协程中直接调用回调可能更高效。在实际项目中应用时,请根据项目的架构和编码规范自由修改后使用。

URL 确认

此 API 使用 service-account.playnanoo.com 域名。

API 信息

  • URL: https://service-account.playnanoo.com/api/v20240401/alive
  • Method: PUT
  • 需要认证: 是

请求参数

参数类型必需说明
platformstring必需平台(例如:"aos"、"ios")
device_idstring必需设备唯一 ID
device_modelstring必需设备型号
device_osstring必需设备 OS
device_languagestring必需设备语言(例如:"KO"、"EN")
DeviceInfo 继承

此 API 的 Req 类继承自 DeviceInfo。DeviceInfo 的所有属性将自动包含。

响应数据

正常响应

字段类型说明
Statusstring状态(正常:"success")

错误响应

错误代码说明
30006DuplicatedDeviceException - 已在其他设备上认证

Unity C# 实现

CheckAlive 类

using System;
using System.Collections;
using UnityEngine.Networking;

public class CheckAlive
{
static string path = "https://service-account.playnanoo.com/api/v20240401/alive";

[Serializable]
public class Req : DeviceInfo
{
public IEnumerator Send(
Action<Res> onSuccess,
Action<BaseResponse> onError)
{
yield return HttpClient.Send<Req, Res>(
UnityWebRequest.kHttpVerbPUT,
path,
requireToken: true,
body: this,
onSuccess: onSuccess,
onError: onError
);
}
}

[Serializable]
public class Res : BaseResponse
{
public string Status;
}
}

在单例管理器类中添加

在单例管理器中定期调用 CheckAlive 并检测重复登录。

// 变量声明
private bool _isDuplicate = false;
private Coroutine _aliveCoroutine;
private Action<bool> _duplicateCallback;

void Update()
{
// 如果注册了重复检测回调且检测到重复,则调用回调
if (_duplicateCallback != null && _isDuplicate)
{
_duplicateCallback.Invoke(true);
_isDuplicate = false; // 调用一次后重置
}
}

// 开始会话保持(最少 300 秒)
public void CheckAliveStart(int delayTime = 300)
{
if (_aliveCoroutine != null) return;
int timer = delayTime < 300 ? 300 : delayTime;
_aliveCoroutine = StartCoroutine(AliveStatus(timer));
}

// 停止会话保持
public void CheckAliveStop()
{
if (_aliveCoroutine != null)
{
StopCoroutine(_aliveCoroutine);
_aliveCoroutine = null;
}
}

IEnumerator AliveStatus(float delayTime)
{
while (true)
{
yield return new WaitForSeconds(delayTime);

if (string.IsNullOrEmpty(DataManager.Instance.AccessToken)) continue;

CheckAlive.Req req = new CheckAlive.Req();
yield return req.Send(
onSuccess: res =>
{
// 正常响应 - 非重复
},
onError: err =>
{
// 30006: DuplicatedDeviceException - 已在其他设备上认证
if (err != null && err.ErrorCode == "30006")
{
_isDuplicate = true;
}
}
);
}
}

// 注册重复登录检测回调
public void CheckDuplicate(Action<bool> callback)
{
_duplicateCallback = callback;
}

使用示例

基本用法

void Start()
{
// 登录成功后开始会话保持(每 300 秒)
YourSingleton.Instance.CheckAliveStart(300);

// 注册重复登录检测回调
YourSingleton.Instance.CheckDuplicate(OnCheckAccountDuplicate);
}

void OnCheckAccountDuplicate(bool isDuplicate)
{
if (isDuplicate)
{
Debug.LogError("Duplicate connection has been detected.");
// 强制登出处理
// 例如:跳转到登录界面、删除令牌等
}
}

登出时停止会话保持

public void Logout()
{
// 停止会话保持
YourSingleton.Instance.CheckAliveStop();

// 其他登出处理...
}

工作流程

  1. 登录成功后调用 CheckAliveStart(300)
  2. 每 300 秒向服务器发送 alive 请求
  3. 正常响应:会话保持
  4. 错误 30006:已在其他设备登录 → _isDuplicate = true
  5. Update():检测到重复时调用注册的回调
  6. 回调处理:强制登出、显示通知等

注意事项

禁止重复调用

CheckAliveStart()整个应用中只能调用一次

  • 不能在多个场景或组件中重复调用。
  • 重复调用时服务器可能会检测到异常请求模式,导致误报(false positive)重复登录错误(30006)
  • 请使用单例模式在一个地方管理会话保持。
  • 虽然在计时器已运行的情况下内部会阻止重复调用,但在结构上建议保持单一调用点。