登录 IM
更新时间: 2024/03/07 11:20:06
完成 NIM SDK 的初始化之后,用户需要先调用 SDK 的登录接口登录 IM。登录成功后,用户才能正常调用消息和会话等其他 SDK 接口。
本文介绍账号集成与登录的技术原理、实现 IM 登录的流程、IM 登录状态转换流程,以及相关常见问题。
技术原理
IM 的登录与账号集成密切相关。上图展示了应用集成 NIM SDK 后,从账号集成到登录 IM 成功的主要流程:
- 用户在应用客户端注册用户账号时,由应用服务端向云信服务端发起创建 IM 帐号的请求。
- IM 帐号创建成功后,云信服务端会返回该 IM 帐号(即
accid)
和token
等信息。此时,应用服务端需要负责保存accid
和token
的映射关系。 - 应用客户端发起登录请求时,先走应用自有的登录验证逻辑,如帐号和密码的验证。
- 验证成功后,应用服务端将与该用户对应的
accid
和token
等信息返回给应用客户端。此时,应用客户端需要负责保存accid
和token
的映射关系。 - 当应用客户端需要调用云信的 IM 服务时,需要先进行
token
验证,以登录 IM 服务。 token
验证成功后,应用客户端登录 IM 服务成功。之后用户便可调用 NIM SDK 的相关接口使用 IM 服务,如进行 IM 消息收发。
- 终端用户使用云信 IM 服务时,应用本身的用户帐号和云信的 IM 账号(
accid
)彼此独立。云信的 IM 账号只用于云信 IM 服务的鉴权,IM 账号并不等同于应用的用户账号。 - 应用的用户帐号和密码,与云信登录 IM 使用的
accid
和token
完全不一致。accid
和token
不由终端用户创建,而是由应用服务端分配,以保证安全性。
前提条件
实现登录 IM
API 调用时序
下图展示了与用户首次登录登出相关的API 的调用时序,图中的 NIM 表示 NIM Flutter SDK。
步骤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 登录的鉴权。
-
注册云信 IM 账号,获取 IM 账号(
accid
)和静态token
。 -
基于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:
|
动态 Token 登录 | 动态 Token 鉴权 | ||
通过第三方回调登录 | 通过第三方回调鉴权 | ||
自动登录 | 继承手动登录的方式 | 继承手动登录的鉴权方式 | 应用被清理后,用户再次点击应用图标启动应用时,无需输入用户名和密码即可完成登录的场景。自动登录需在手动登录成功后使用 |
推荐在手动登录成功后,将accid
和token
保存到本地,方便下次应用启动进行初始化时,在NIMSDKOptions
的autoLoginInfo
中传入,实现自动登录。更多相关说明,参见IM 登录最佳实践。
方式1:手动登录
静态 Token 登录
调用login
方法手动登录 IM。调用时需将authType
参数设置为 authTypeDefault
。
调用后,NIM SDK 会自动连接云信服务端,传递用户信息,返回登录结果。登录过程中可主动取消登录。如果因为网络或其他原因导致云信服务端长时间未响应,用户也没有主动取消登录,NIM SDK 将在 45 秒后自动重新连接云信服务端,并返回错误码,错误码详情参见下文的手动登录错误码。
NIMLoginInfo 参数 |
是否必传 | 说明 |
---|---|---|
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,需完成如下两步操作:
-
通过
AuthService#dynamicTokenProvider
方法获取上文中提及的基于App Secret生成的动态Token。 -
调用
login
方法手动登录 IM,调用时需将authType
设置为 authTypeDynamic。调用后,NIM SDK 会自动连接云信服务端,传递用户信息,返回登录结果。登录过程中可主动取消登录。如果因为网络或其他原因导致云信服务端长时间未响应,用户也没有主动取消登录,NIM SDK 将在 45 秒后自动重新连接云信服务端,并返回错误码,错误码详情参见下文的手动登录错误码。
具体参数说明如下:
NIMLoginInfo
参数是否必传 说明 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 步操作:
-
前往云信控制台,并进入IM 免费版/专业版 > 功能配置 > 第三方回调配置第三方回调的环境地址(即第三方服务器地址)和回调失败时放行(通过)与否。
-
调用
login
方法手动登录 IM,调用时需将authType
设置为 authTypeThirdParty,且必须传入loginExt
。调用后,NIM SDK 会自动连接云信服务端,传递用户信息,返回登录结果。登录过程中可主动取消登录。如果因为网络或其他原因导致云信服务端长时间未响应,用户也没有主动取消登录,NIM SDK 将在 45 秒后自动重新连接云信服务端,并返回错误码,错误码详情参见下文的手动登录错误码。
具体参数说明如下:
NIMLoginInfo
参数是否必传 说明 account
是 用户的 IM 账号,即 accid
authType
该登录方式必传 采用动态 token
登录时必须传入 authTypeThirdParty,表示通过第三方回调进行鉴权loginExt
该登录方式必传 登录自定义扩展字段,长度上限为 1k 字符。采用该登录方式时,必须传入,用于第三方服务器鉴权。如未传入,将返回 LoginInfo is invalid
的报错信息token
视情况而定 获取到的静态 token
。采用动态token
登录时,如果您的应用不需要调用云信的聊天室能力,那么不需要传入静态token
;如果需要,那么必须传入静态token
customClientType
否 自定义客户端类型,小于或等于 0 则视为没有自定义类型 -
发起登录相关回调的请求,由第三方服务器进行鉴权并判定 IM 登录事件是否放行通过。
若不通过,云信服务端将返回 302 错误码。
方式2:自动登录
自动登录一般用于应用被清理后,用户再次点击应用图标启动应用时,无需输入用户名和密码即可完成登录的场景。此时应用可以在无网络、未登录成功的状态下直接访问用户本地 SDK 数据。自动登录与手动登录在客户端侧和服务端逻辑上的区别,参见文末的常见问题。
实现自动登录的方式为,在调用initialize
方法初始化 SDK 时,将本地保存的account
和token
传入NIMAndroidSDKOptions
或NIMIOSSDKOptions
的自动登录信息(autoLoginInfo
)。
- 推荐参考自动登录最佳实践和登录状态处理最佳实践实现自动登录以及相应的登录状态处理逻辑。
- 目前仅 Android 和 iOS 支持自动登录, Windows 和 macOS 不支持。
示例代码如下:
dartNimCore.instance.initialize(
NIMAndroidSDKOptions(
appKey: 'appkey',
autoLoginInfo: NIMLoginInfo(
account: 'account',
token: 'token',
),
),
).then(
(result) {
if (result.isSuccess) {
/// 初始化成功
} else {
/// 初始化失败
}
},
);
相关信息
手动登录错误码
手动登录失败的错误码说明如下:
错误码 | 说明 |
---|---|
302 | App Key、accid 和token 三者不对应 |
408 | 与云信服务端的连接超时 |
415 | 网络断开或者连接云信服务端失败 |
416 | 调用手动登录接口过于频繁 |
1000 | 本地数据库未打开。请在手动登录成功后打开本地数据库 |
断网重连机制
SDK 提供了自动重连机制(自动重新建立与云信服务端的连接并重新登录),所有重连的登录状态变更都会触发NIMAuthStatusEvent
事件回调。
SDK 在两种场景下会自动进行重连:
- 手动/自动登录成功后,网络不佳导致连接断开的情况。
- 网络不佳时,账号密码本身正常(未被封禁,且账号密码均正确),启动应用时调用自动登录接口的情况。
满足上述中一个条件,当用户遇到普通网络问题如连接超时等,会自动进行重连登录,不需要上层开发者去做额外的重登逻辑。
多端登录与互踢
当前 NIM SDK 支持配置四种不同的 IM 多端登录与互踢策略,具体参见多端登录与互踢。
登录状态转换流程
登录状态变化流程(不包含被踢下线和被 IM 服务端禁止登录等特殊状态)参见下图。图中,深蓝色元素代表登录状态,浅绿色元素代表自动登录或调用login
方法的手动登录。
常见问题
手动登录和自动登录的主要区别是什么?
手动登录和自动登录主要在于:
差异点 |
说明 |
---|---|
NIM SDK 是否接管登录失败后的处理 |
|
云信服务端是否验证当前登录设备的安全性 |
|
如您选择自动登录,当您的应用在后台被唤起时,会计算为1次登录行为,计入日活统计作为计费依据。
断线后是否会自动重连?
一旦登录成功后(或者调用过自动登录),NIM SDK 将接管所有的重连情况:在网络正常的情况下不停重试重连直到正常登录为止,并不需要做额外的登录操作(聊天室同理)。
如何根据产品形态选择 IM 登录方式?
接入网易云信 IM 服务的产品大致分为两种形态:
- IM 产品:通讯作为其核心模块。典型例子如微信、易信、网络直播相关应用。
- 非 IM 产品:通讯只是其附带模块,典型例子如各种有私信模块的应用。
对于 IM 产品,由于通讯能力是核心能力,如果云信无法登录成功则整个应用将无法正常表现,所以推荐在执行业务逻辑前,首先完成应用服务端和云信服务端的登录。只有应用服务端和云信服务端都登录成功才认为整个登录完成。而对于非 IM 产品而言,通讯能力是可以在登录应用服务端成功后延迟加载,登录成功拿到服务端下发的云信 IM 账号和 token
后进行自动登录即可。