Flutter

登录 IM

更新时间: 2024/03/07 11:20:06

完成 NIM SDK 的初始化之后,用户需要先调用 SDK 的登录接口登录 IM。登录成功后,用户才能正常调用消息和会话等其他 SDK 接口。

本文介绍账号集成与登录的技术原理、实现 IM 登录的流程、IM 登录状态转换流程,以及相关常见问题

技术原理

IM 的登录与账号集成密切相关。上图展示了应用集成 NIM SDK 后,从账号集成到登录 IM 成功的主要流程:

  1. 用户在应用客户端注册用户账号时,由应用服务端向云信服务端发起创建 IM 帐号的请求。
  2. IM 帐号创建成功后,云信服务端会返回该 IM 帐号(即accid)token等信息。此时,应用服务端需要负责保存accidtoken的映射关系。
  3. 应用客户端发起登录请求时,先走应用自有的登录验证逻辑,如帐号和密码的验证。
  4. 验证成功后,应用服务端将与该用户对应的accidtoken等信息返回给应用客户端。此时,应用客户端需要负责保存accidtoken的映射关系。
  5. 当应用客户端需要调用云信的 IM 服务时,需要先进行token验证,以登录 IM 服务。
  6. token验证成功后,应用客户端登录 IM 服务成功。之后用户便可调用 NIM SDK 的相关接口使用 IM 服务,如进行 IM 消息收发。
  • 终端用户使用云信 IM 服务时,应用本身的用户帐号和云信的 IM 账号(accid彼此独立。云信的 IM 账号只用于云信 IM 服务的鉴权,IM 账号并不等同于应用的用户账号
  • 应用的用户帐号和密码,与云信登录 IM 使用的 accidtoken 完全不一致。accidtoken 不由终端用户创建,而是由应用服务端分配,以保证安全性。

前提条件

  • 已完成初始化
  • 已在云信控制台配置应用的 IM 登录策略。如未配置相应的登录策略,可能导致后续调用登录接口时因无登录权限而报错(状态码:403)。
  • (可选)已在控制台配置客户端应用标识

实现登录 IM

API 调用时序

下图展示了与用户首次登录登出相关的API 的调用时序,图中的 NIM 表示 NIM Flutter SDK。

uml diagram

步骤1:准备 Token

登录 IM 需要通过 Token 进行鉴权。云信支持静态和动态两种 Token 类型,您可根据业务需求进行选择。

  • 静态 Token:默认为永久有效。如有需要,可通过云信服务端 API 主动刷新 Token

  • 动态 Token:具备时效性,可在生成时设置有效期。

获取静态 Token

  • 方式1:在控制台获取静态Token

    如果您只需要进行简单的体验或者快速测试,那么可以在云信控制台创建测试用的 IM 账号,并获取与该 IM 账号相应的静态token,具体参见注册调试用的 IM 账号。获取的静态token可用于下文提及的静态 Token 登录

    该方式仅 IM 免费版支持。如已升级为 IM 专业版,则需要调用服务端 API 获取静态token

  • 方式2:调用服务端 API 获取静态Token

    如果您有正式的生产环境,且您的业务仅需保障基础的用户信息安全,那么可通过云信 IM 服务端 API 注册 IM 账号,并获取与之相对应的静态token,具体参见注册云信 IM 账号。获取的静态token可用于静态 Token 登录的鉴权。

获取动态 Token

如果您有正式的生产环境,且您的业务对用户信息安全有较高的要求,可使用动态token。动态token可用于动态 Token 登录的鉴权。

  1. 注册云信 IM 账号,获取 IM 账号(accid)和静态token

  2. 基于App Key、App Secret 和accid,通过约定算法在应用服务端生成动态token

如果使用该方式,且您的应用需要调用云信的聊天室能力,那么要实现动态 token 登录,既要传入动态token(通过下文提及的AuthService#dynamicTokenProvider),也要传入静态token

步骤2:监听登录状态

通过登录状态事件流(authStatus)监听当前登录状态。

目前登录状态事件包含两类:

  • NIMAuthStatusEvent:通用登录状态事件,包含 NIMAuthStatus 登录状态枚举(具体枚举值见下表)。
  • NIMKickOutByOtherClientEvent:被踢事件,包含状态字段与额外属性;在使用时,需要根据具体类型进行解析。
NIMAuthStatus 说明
unknown 未定义
unLogin 未登录/登录失败
netBroken 网络连接已断开
connecting 正在连接云信服务端
logging 正在登录中
loggedIn 已成功登录
kickOut 被其他端的登录踢掉,此时应该跳转至手动登录界面。被踢后,无法自动登录
kickOutByOtherClient 被同时在线的其他端主动踢掉(通过kickOutOtherOnlineClient方法),此时应该跳转至手动登录界面。被踢后,无法自动登录
forbidden 被云信服务端禁止登录云信 IM 账号被禁用。被禁止登录后,无法自动登录
versionError SDK 版本错误。出现该登录异常后,无法自动登录
pwdError 云信 IM 账号(account)或 token 错误。出现该登录异常后,无法自动登录
  • SDK 暂不支持主动查询当前账号是否处于在线状态,请监听登录状态变化并进行状态缓存。
  • 登录状态变化流程相关详情,请参见下文的登录状态变化流程

示例代码如下:

dart    /// 开始监听事件
    final subscription = NimCore.instance.authService.authStatus.listen((event) {
      if (event is NIMKickOutByOtherClientEvent) {
        /// 监听到被踢事件
      } else if (event is NIMAuthStatusEvent) {
        /// 监听到其他事件
      }
    });

    /// 不再监听时,需要取消监听,否则造成内存泄漏
    /// subscription.cancel();

步骤3:监听数据同步状态

登录成功后,SDK 会自动同步群信息、离线消息、漫游消息和系统通知等数据。数据同步过程会广播数据同步状态变更事件(NIMDataSyncStatusEvent),可通过以下接口监听该事件。

dartclass AuthService {
    /// 登录状态变更事件
    Stream<NIMAuthStatusEvent> get authStatus;
}

数据同步状态事件包含一个类型为 NIMAuthStatus 的登录状态字段,标识当前同步状态:

NIMAuthStatus 说明
NIMAuthStatus.dataSyncStart 数据同步开始
NIMAuthStatus.dataSyncFinish 数据同步完成
  • Windows 和 macOS 暂不支持监听数据同步状态变化。
  • 数据同步完成时,整个登录过程才算真正完成。

示例代码如下:

dart    /// 开始监听事件
    final subscription = NimCore.instance.authService.authStatus.listen((event) {
      if (event is NIMDataSyncStatusEvent) {
        /// 监听到数据同步事件
        if (event.status == NIMAuthStatus.dataSyncStart) {
          /// 数据同步开始
        } else if (event.status == NIMAuthStatus.dataSyncFinish) {
          /// 数据同步完成
        }
      }
    });

    /// 不再监听时,需要取消监听,否则造成内存泄漏
    /// subscription.cancel();

步骤4:登录 IM

登录方式概览

NIM SDK 登录方式分为两大类,即手动登录和自动登录。其中手动登录可进一步分为静态token登录、动态token登录和通过第三方回调登录。

您可按需实现一种或多种手动登录方式,并在手动登录成功后,实现自动登录。

登录方式
子方式 鉴权方式 使用场景
手动登录 静态 Token 登录 静态 Token 鉴权 如下登录场景,用户需要手动登录 IM:
  • 在新设备上首次登录 IM
  • 被同时在线的其他设备踢下线后再次登录 IM
  • 切换 IM 账号后再次登录 IM
  • 注销登录后再次登录 IM
动态 Token 登录 动态 Token 鉴权
通过第三方回调登录 通过第三方回调鉴权
自动登录 继承手动登录的方式 继承手动登录的鉴权方式 应用被清理后,用户再次点击应用图标启动应用时,无需输入用户名和密码即可完成登录的场景。自动登录需在手动登录成功后使用

推荐在手动登录成功后,将accidtoken保存到本地,方便下次应用启动进行初始化时,在NIMSDKOptionsautoLoginInfo中传入,实现自动登录。更多相关说明,参见IM 登录最佳实践

方式1:手动登录

静态 Token 登录

调用login方法手动登录 IM。调用时需将authType参数设置为 authTypeDefault

调用后,NIM SDK 会自动连接云信服务端,传递用户信息,返回登录结果。登录过程中可主动取消登录。如果因为网络或其他原因导致云信服务端长时间未响应,用户也没有主动取消登录,NIM SDK 将在 45 秒后自动重新连接云信服务端,并返回错误码,错误码详情参见下文的手动登录错误码

是否必传 说明
account 用户的 IM 账号,即accid
token 获取到的静态token
authType 登录 IM 的鉴权方式。采用静态token登录时,使用默认的 authTypeDefault 即可,即静态token鉴权
customClientType 自定义客户端类型,小于或等于 0 则视为没有自定义类型

示例代码如下:

dartNimCore.instance.authService
    .login(NIMLoginInfo(account: 'account', token: 'token',))
    .then(
      (result) {
        if (result.isSuccess) {
          /// 登录成功
        } else {
          /// 登录失败
        }
      },
    );
动态 Token 登录

动态token具备时效性,可有效提升token破解难度,降低密码泄露风险。

要实现动态token登录 IM,需完成如下两步操作:

  1. 通过AuthService#dynamicTokenProvider方法获取上文中提及的基于App Secret生成的动态Token

  2. 调用login方法手动登录 IM,调用时需将authType设置为 authTypeDynamic

    调用后,NIM SDK 会自动连接云信服务端,传递用户信息,返回登录结果。登录过程中可主动取消登录。如果因为网络或其他原因导致云信服务端长时间未响应,用户也没有主动取消登录,NIM SDK 将在 45 秒后自动重新连接云信服务端,并返回错误码,错误码详情参见下文的手动登录错误码

    具体参数说明如下:

    是否必传 说明
    account 用户的 IM 账号,即accid
    authType 该登录方式必传 采用动态token登录时必须传入 authTypeDynamic,表示通过动态token鉴权,动态token基于 App Secret 计算生成
    token 视情况而定 获取到的静态 token。采用动态token登录时,如果您的应用不需要调用云信的聊天室能力,那么不需要传入静态token;如果需要,那么必须传入静态token
    customClientType 自定义客户端类型,小于或等于 0 则视为没有自定义类型

示例代码如下:

NimCore.instance.authService.dynamicTokenProvider = (account) async {
        //...生成动态token
        return token;
      };

loginResult = await NimCore.instance.authService.login(NIMLoginInfo(
        account: account,
        token: token,
        authType: NIMAuthType.authTypeDynamic,
      ));
通过第三方回调登录

如采用该登录方式,云信服务端不做 IM 登录鉴权,鉴权工作需由指定的第三方服务器(可以是应用服务器)进行。

实现该登录方式,需完成如下 3 步操作:

  1. 前往云信控制台,并进入IM 免费版/专业版 > 功能配置 > 第三方回调配置第三方回调的环境地址(即第三方服务器地址)和回调失败时放行(通过)与否。

    第三方回调配置文案优化后.png

  2. 调用login方法手动登录 IM,调用时需将authType设置为 authTypeThirdParty,且必须传入loginExt

    调用后,NIM SDK 会自动连接云信服务端,传递用户信息,返回登录结果。登录过程中可主动取消登录。如果因为网络或其他原因导致云信服务端长时间未响应,用户也没有主动取消登录,NIM SDK 将在 45 秒后自动重新连接云信服务端,并返回错误码,错误码详情参见下文的手动登录错误码

    具体参数说明如下:

    是否必传 说明
    account 用户的 IM 账号,即accid
    authType 该登录方式必传 采用动态token登录时必须传入 authTypeThirdParty,表示通过第三方回调进行鉴权
    loginExt 该登录方式必传 登录自定义扩展字段,长度上限为 1k 字符。采用该登录方式时,必须传入,用于第三方服务器鉴权。如未传入,将返回 LoginInfo is invalid 的报错信息
    token 视情况而定 获取到的静态 token。采用动态token登录时,如果您的应用不需要调用云信的聊天室能力,那么不需要传入静态token;如果需要,那么必须传入静态token
    customClientType 自定义客户端类型,小于或等于 0 则视为没有自定义类型
  3. 发起登录相关回调的请求,由第三方服务器进行鉴权并判定 IM 登录事件是否放行通过。

    若不通过,云信服务端将返回 302 错误码。

方式2:自动登录

自动登录一般用于应用被清理后,用户再次点击应用图标启动应用时,无需输入用户名和密码即可完成登录的场景。此时应用可以在无网络、未登录成功的状态下直接访问用户本地 SDK 数据。自动登录与手动登录在客户端侧和服务端逻辑上的区别,参见文末的常见问题

实现自动登录的方式为,在调用initialize方法初始化 SDK 时,将本地保存的accounttoken传入NIMAndroidSDKOptionsNIMIOSSDKOptions的自动登录信息(autoLoginInfo)。

示例代码如下:

dartNimCore.instance.initialize(
  NIMAndroidSDKOptions(
    appKey: 'appkey',
    autoLoginInfo: NIMLoginInfo(
      account: 'account',
      token: 'token',
    ),
  ),
).then(
  (result) {
    if (result.isSuccess) {
      /// 初始化成功
    } else {
      /// 初始化失败
    }
  },
);

相关信息

手动登录错误码

手动登录失败的错误码说明如下:

错误码 说明
302 App Key、accidtoken三者不对应
408 与云信服务端的连接超时
415 网络断开或者连接云信服务端失败
416 调用手动登录接口过于频繁
1000 本地数据库未打开。请在手动登录成功后打开本地数据库

断网重连机制

SDK 提供了自动重连机制(自动重新建立与云信服务端的连接并重新登录),所有重连的登录状态变更都会触发NIMAuthStatusEvent事件回调。

SDK 在两种场景下会自动进行重连:

  • 手动/自动登录成功后,网络不佳导致连接断开的情况。
  • 网络不佳时,账号密码本身正常(未被封禁,且账号密码均正确),启动应用时调用自动登录接口的情况。

满足上述中一个条件,当用户遇到普通网络问题如连接超时等,会自动进行重连登录,不需要上层开发者去做额外的重登逻辑

多端登录与互踢

当前 NIM SDK 支持配置四种不同的 IM 多端登录与互踢策略,具体参见多端登录与互踢

登录状态转换流程

登录状态变化流程(不包含被踢下线和被 IM 服务端禁止登录等特殊状态)参见下图。图中,深蓝色元素代表登录状态,浅绿色元素代表自动登录或调用login方法的手动登录。

unLogin
unLogin
connecting
connecting
网络连接是否良好
网络连接是否良好
netBroken
netBroken
是否存在物理网络
是否存在物理网络
connecting
connecting
网络连接是否良好
网络连接是否良好
logging
logging
网络连接是否良好
网络连接是否良好
loggedIn
loggedIn
网络连接是否良好
网络连接是否良好
开始
开始
连接/重连
连接/重连
Text is not SVG - cannot display

常见问题

手动登录和自动登录的主要区别是什么?

手动登录和自动登录主要在于:

差异点
说明
NIM SDK 是否接管登录失败后的处理
  • 手动登录:NIM SDK 认为手动登录即是终端用户发起登录的流程,因此在登录失败后(如网络情况不佳、密码错误),NIM SDK 会触发相应回调,并停止重连操作,等待用户再次发起登录操作
  • 自动登录:自动登录失败后仍旧尝试重连,直到登录成功为止(密码错误等情况除外)
云信服务端是否验证当前登录设备的安全性
  • 手动登录:不验证
  • 自动登录:自动登录时,如果当前登录设备不是上一次登录设备,云信服务端会自动禁止其登录,以保证安全性。

如您选择自动登录,当您的应用在后台被唤起时,会计算为1次登录行为,计入日活统计作为计费依据。

断线后是否会自动重连?

一旦登录成功后(或者调用过自动登录),NIM SDK 将接管所有的重连情况:在网络正常的情况下不停重试重连直到正常登录为止,并不需要做额外的登录操作(聊天室同理)。

如何根据产品形态选择 IM 登录方式?

接入网易云信 IM 服务的产品大致分为两种形态:

  • IM 产品:通讯作为其核心模块。典型例子如微信、易信、网络直播相关应用。
  • 非 IM 产品:通讯只是其附带模块,典型例子如各种有私信模块的应用。

对于 IM 产品,由于通讯能力是核心能力,如果云信无法登录成功则整个应用将无法正常表现,所以推荐在执行业务逻辑前,首先完成应用服务端和云信服务端的登录。只有应用服务端和云信服务端都登录成功才认为整个登录完成。而对于非 IM 产品而言,通讯能力是可以在登录应用服务端成功后延迟加载,登录成功拿到服务端下发的云信 IM 账号和 token 后进行自动登录即可。

此文档是否对你有帮助?
有帮助
去反馈
  • 技术原理
  • 前提条件
  • 实现登录 IM
  • API 调用时序
  • 步骤1:准备 Token
  • 获取静态 Token
  • 获取动态 Token
  • 步骤2:监听登录状态
  • 步骤3:监听数据同步状态
  • 步骤4:登录 IM
  • 登录方式概览
  • 方式1:手动登录
  • 静态 Token 登录
  • 动态 Token 登录
  • 通过第三方回调登录
  • 方式2:自动登录
  • 相关信息
  • 手动登录错误码
  • 断网重连机制
  • 多端登录与互踢
  • 登录状态转换流程
  • 常见问题
  • 手动登录和自动登录的主要区别是什么?
  • 断线后是否会自动重连?
  • 如何根据产品形态选择 IM 登录方式?