登录及登出 IM

更新时间: 2024/04/17 15:00:35

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

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

支持平台

Android iOS Windows/macOS Web/uni-app/小程序 Harmony

技术原理

账号登录流程

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

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

登录方式

根据鉴权方式,登录方式分为静态 Token 登录、动态 Token 登录和通过第三方回调登录。

您可按需实现一种或多种登录方式。

登录方式
鉴权方式 描述
静态 Token 登录 静态 Token 鉴权 静态 Token 默认永久有效,且恒定不变,除非主动调用服务端接口刷新。
动态 Token 登录 动态 Token 鉴权 动态 Token 具备时效性,适用于对于用户信息安全有较高要求的业务场景。
通过第三方回调登录 通过第三方回调鉴权 用户登录 IM 时的鉴权工作由指定的第三方服务器(可以是应用服务器)进行,云信服务端不做 IM 登录鉴权

更多相关说明,请参见 IM 登录最佳实践

前提条件

配置 IM 登录策略

登录策略指您的应用需要采用的一种或多种 IM 登录方式。登录 IM 前,您需要在云信控制台配置应用的 IM 登录策略。如未配置相应的登录策略,后续调用登录接口时可能因无登录权限而报错(状态码:403)。

  1. 云信控制台首页应用管理选择应用进入应用配置页面,然后单击 IM即时通讯 专业版IM即时通讯 免费版下的功能配置按钮进入 IM 即时通讯配置页。

  2. 在顶部选择基础功能页签,配置登录策略

  • 静态 Token 登录:用户登录 IM 时需传入静态 Token。静态 Token 默认永久有效,且恒定不变,除非主动调用新版服务端 API 刷新 Token
  • 动态 Token 登录:用户登录 IM 时需传入动态 Token。动态 Token 具备时效性,适用于对于用户信息安全有较高要求的业务场景。
  • 通过第三方回调登录:用户登录 IM 时的鉴权工作由指定的第三方服务器(可以是应用服务器)进行,云信服务端不做 IM 登录鉴权。选择第三方回调后,请至第三方回调配置进行相关设置。

实现登录 IM

步骤1:准备 Token

根据以上配置的登录策略,您需要获取对应的 Token 以供后续鉴权。

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

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

  • 动态登录扩展数据(LoginExtension):适用于所有登录模式。如果在第三方回调登录模式中设置动态登录扩展数据,第三方服务器可使用该值来进行鉴权。

获取静态 Token

您可以通过以下两种方式获取静态 Token,用于静态 Token 登录的鉴权。

  • 方式一:在云信控制台获取静态 Token

    如果您只需进行简单的体验或快速测试,那么可以在云信控制台创建 IM 测试账号,并获取与该账号对应的静态 Token,获取方式详见注册 IM 账号

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

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

获取动态 Token

如果您有正式的生产环境,且您的业务对用户信息安全有较高的要求,可选择动态 Token 登录。获取动态 Token 步骤如下:

  1. 注册 IM 账号,获取 accountId

    • 方式一:在云信控制台注册 IM 测试账号

      如果您只需进行简单的体验或快速测试,那么可以在云信控制台创建 IM 测试账号,详见注册 IM 账号

    • 方式二:调用服务端 API 注册 IM 正式账号

      如果您有正式的生产环境,且您的业务需保障基础的用户信息安全,那么可通过云信 IM 新版服务端 API 注册 IM 正式账号

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

  3. 客户端可在登录时通过 V2NIMLoginOption#tokenProvider,从回调中获取动态 Token。具体实现方式详见下文动态 Token 登录

获取动态登录扩展数据

客户端可在登录时通过 V2NIMLoginOption#loginExtensionProvider,从回调中获取动态登录扩展数据。具体实现方式详见下文通过第三方回调登录

步骤2:注册登录相关事件监听

1. 注册登录状态相关监听

Android/iOS/macOS/Windows

调用 addLoginListener 方法注册登录相关监听器,包括登录状态变化、登录失败、登录终端被踢、登录终端信息变更。

  • 相关回调:

    • onLoginStatus:登录状态变化回调
    • onLoginFailed:登录失败回调
    • onKickedOffline:登录终端被其他端踢下线回调
    • onLoginClientChanged:登录终端登录信息变更回调
  • 示例代码:

    Android
    javaNIMClient.getService(V2NIMLoginService.class).addLoginListener(new V2NIMLoginListener() {
        @Override
        public void onLoginStatus(V2NIMLoginStatus status) {
            // Handle login status
        }
        @Override
        public void onLoginFailed(V2NIMError error) {
            // Handle login error
        }
        @Override
        public void onKickedOffline(V2NIMKickedOfflineDetail detail) {
            // Handle kicked offline detail
        }
        @Override
        public void onLoginClientChanged(V2NIMLoginClientChange change, List<V2NIMLoginClient> clients) {
            // Handle login client change
        }
    });
    
    iOS
    objective-c@interface V2NIMLoginServiceSample : NSObject<V2NIMLoginListener>
    
    @end
    
    @implementation V2NIMLoginServiceSample
    
    - (void)listen {
        [[[NIMSDK sharedSDK] v2LoginService] addLoginListener:self];
    }
    
    - (void)onLoginStatus:(V2NIMLoginStatus)status {
        // Handle login status
    }
    
    - (void)onLoginFailed:(V2NIMError *)error {
        // Handle login error
    }
    
    - (void)onKickedOffline:(V2NIMKickedOfflineDetail *)detail {
        // Handle kicked offline detail
    }
    
    - (void)onLoginClientChanged:(V2NIMLoginClientChange)change clients:(nullable NSArray<V2NIMLoginClient *> *)clients {
        // Handle login client change
    }
    
    @end
    
    macOS/Windows
    cppV2NIMLoginListener listener;
    listener.onLoginStatus = [](V2NIMLoginStatus status) {
        // Handle login status
    };
    listener.onLoginFailed = [](V2NIMError error) {
        // Handle login error
    };
    listener.onKickedOffline = [](V2NIMKickedOfflineDetail detail) {
        // Handle kicked offline detail
    };
    listener.onLoginClientChanged = [](V2NIMLoginClientChange change, std::vector<V2NIMLoginClient> clients) {
        // Handle login client change
    };
    loginService.addLoginListener(listener);
    

    如需移除登录相关监听器,可调用 removeLoginListener

    Android
    javaNIMClient.getService(V2NIMLoginService.class).removeLoginListener(listener);
    
    iOS
    objective-cid<V2NIMLoginListener> listener;
    [[[NIMSDK sharedSDK] v2LoginService] removeLoginListener:listener];
    
    macOS/Windows
    cppV2NIMLoginListener listener;
    loginService.removeLoginListener(listener);
    

Web/uni-app/小程序/Harmony

调用 on("EventName") 方法注册登录相关监听器,包括登录状态变化、登录失败、登录终端被踢、登录终端信息变更。

  • 相关回调:

    • onLoginStatus:登录状态变化回调
    • onLoginFailed:登录失败回调
    • onKickedOffline:登录终端被其他端踢下线回调
    • onLoginClientChanged:登录终端登录信息变更回调
  • 示例代码:

    Web/uni-app/小程序
    typescriptnim.V2NIMLoginService.on("onLoginStatus", theListnerFn)
    nim.V2NIMLoginService.on("onLoginFailed", theListnerFn)
    nim.V2NIMLoginService.on("onKickedOffline", theListnerFn)
    nim.V2NIMLoginService.on("onLoginClientChanged", theListnerFn)
    

    如需移除登录相关监听器,可调用 off("EventName")

    typescriptnim.V2NIMLoginService.off("onLoginStatus")
    nim.V2NIMLoginService.off("onLoginFailed")
    nim.V2NIMLoginService.off("onKickedOffline")
    nim.V2NIMLoginService.off("onLoginClientChanged")
    
    Harmony
    typescriptnim.loginService.on("onLoginStatus", (status: V2NIMLoginStatus) => {})
    nim.loginService.on("onLoginFailed", (error: V2NIMError) => {})
    nim.loginService.on("onKickedOffline", (detail: V2NIMKickedOfflineDetail) => {})
    nim.loginService.on("onLoginClientChanged", (change: V2NIMLoginClientChange, clients: V2NIMLoginClient[]) => {})
    

    如需移除登录相关监听器,可调用 off("EventName")

    typescriptnim.loginService.off("onLoginStatus", theListnerFn)
    nim.loginService.off("onLoginFailed", theListnerFn)
    nim.loginService.off("onKickedOffline", theListnerFn)
    nim.loginService.off("onLoginClientChanged", theListnerFn)
    

2. 注册登录连接状态监听

登录 IM 时,客户端会与 IM 服务端建立长连接,连接成功则登录成功。

Android/iOS/macOS/Windows

登录 IM 成功后,SDK 会自动同步离线消息、漫游消息、用户信息、群信息、系统通知等数据。数据同步完成时,整个登录过程才算真正完成

调用 addLoginDetailListener 方法注册登录连接状态监听器,包括登录连接状态变化、断开连接、连接失败、数据同步状态。

  • 相关回调:

    • onConnectStatus:登录连接状态变化回调
    • onDisconnected:登录连接断开回调
    • onConnectFailed:登录连接失败回调
    • onDataSync:数据同步状态变化回调。发送消息等后续操作要求数据库处于开启状态,否则可能导致发送消息失败,或者阻塞等待数据库开启。
  • 示例代码:

    Android
    javaNIMClient.getService(V2NIMLoginService.class).addLoginDetailListener(new V2NIMLoginDetailListener() {
    
        @Override
        public void onConnectStatus(V2NIMConnectStatus status) {
            // TODO     
        }
        
        @Override
        public void onDisconnected(V2NIMError error) {
            // TODO     
        }
        
        @Override
        public void onConnectFailed(V2NIMError error) {
            // TODO     
        }
    
        @Override
        public void onDataSync(V2NIMDataSyncType type, V2NIMDataSyncState state, V2NIMError error) {
            // TODO     
        }
    });
    
    iOS
    objective-c@interface V2NIMLoginServiceSample : NSObject <V2NIMLoginDetailListener>
    
    @end
    
    @implementation V2NIMLoginServiceSample
    
    - (void)listen {
        [[[NIMSDK sharedSDK] v2LoginService] addLoginDetailListener:self];
    }
    
    - (void)onConnectStatus:(V2NIMConnectStatus)status {
        // Handle connect status
    }
    
    - (void)onDisconnected:(nullable V2NIMError *)error {
        // Handle disconnected error
    }
    
    - (void)onConnectFailed:(nullable V2NIMError *)error {
        // Handle connect failed error
    }
    
    - (void)onDataSync:(V2NIMDataSyncType)type
                state:(V2NIMDataSyncState)state
                error:(nullable V2NIMError *)error {
        // Handle data sync
    }
    
    @end
    
    macOS/Windows
    C++V2NIMLoginDetailListener listener;
    listener.onConnectStatus = [](V2NIMConnectStatus status) {
        // handle connect status change event
    };
    listener.onDisconnected = [](V2NIMError error) {
        // handle disconnected error
    };
    listener.onConnectFailed = [](V2NIMError error) {
        // handle connect failed error
    };
    listener.onDataSync = [](V2NIMDataSync dataSync, bool begin, V2NIMError error) {
        // handle data sync event
    };
    loginService.addLoginDetailListener(listener);
    

    如需移除登录连接状态监听器,可调用 removeLoginDetailListener

    Android
    javaNIMClient.getService(V2NIMLoginService.class).removeLoginDetailListener(listener);
    
    iOS
    objective-cid<V2NIMLoginDetailListener> listener;
    [[[NIMSDK sharedSDK] v2LoginService] removeLoginDetailListener:listener];
    
    macOS/Windows
    cppV2NIMLoginDetailListener listener;
    loginService.removeLoginDetailListener(listener);
    

Web/uni-app/小程序/Harmony

登录 IM 成功后,SDK 会自动同步离线消息、漫游消息、用户信息、群信息、系统通知等数据。数据同步完成时,整个登录过程才算真正完成

调用 on("EventName") 方法注册登录连接状态监听器,包括登录连接状态变化、断开连接、连接失败、数据同步状态。

  • 相关回调:

    • onConnectStatus:登录连接状态变化回调
    • onDisconnected:登录连接断开回调
    • onConnectFailed:登录连接失败回调
    • onDataSync:数据同步状态变化回调。发送消息等后续操作要求数据库处于开启状态,否则可能导致发送消息失败,或者阻塞等待数据库开启。
  • 示例代码:

    Web/uni-app/小程序
    typescriptnim.V2NIMLoginService.on("onConnectStatus", function (status: V2NIMConnectStatus) {})
    nim.V2NIMLoginService.on("onDisconnected", function (error: V2NIMError) {})
    nim.V2NIMLoginService.on("onConnectFailed", function (error: V2NIMError) {})
    nim.V2NIMLoginService.on("onDataSync", function (type: V2NIMDataSyncType, state:    V2NIMDataSyncState, error?: V2NIMError) {})
    

    如需移除登录连接状态监听器,可调用 off("EventName")

    typescriptnim.V2NIMLoginService.off("onConnectStatus")
    nim.V2NIMLoginService.off("onDisconnected")
    nim.V2NIMLoginService.off("onConnectFailed")
    nim.V2NIMLoginService.off("onDataSync")
    
    Harmony
    typescriptnim.loginService.on("onConnectStatus", (status: V2NIMConnectStatus) => {})
    nim.loginService.on("onDisconnected", (error: V2NIMError) => {})
    nim.loginService.on("onConnectFailed", (error: V2NIMError) => {})
    nim.loginService.on("onDataSync", (type: V2NIMDataSyncType, state: V2NIMDataSyncState, error?: V2NIMError) => {})
    

    如需移除登录连接状态监听器,可调用 off("EventName")

    typescriptnim.loginService.off("onConnectStatus", theListner)
    nim.loginService.off("onDisconnected", theListner)
    nim.loginService.off("onConnectFailed", theListner)
    nim.loginService.off("onDataSync", theListner)
    

步骤3:登录 IM

静态 Token 登录

调用 login 方法登录 IM,鉴权方式为静态 Token 鉴权。

调用后,SDK 会自动连接 IM 服务端,传递用户信息并返回登录结果。登录过程中用户可主动取消登录。如果因为网络或其他原因导致 IM 服务端长时间未响应,用户未主动取消登录,SDK 将在 45 秒后自动重连 IM 服务端,并返回错误码

  • 登录部分参数说明:

    参数名称 类型 是否必填 默认值 描述
    accountId String - IM 为用户分配的唯一登录账号。通过云信控制台获取或调用新版服务端 API 注册。获取方式详见获取静态 Token
    token String - 静态鉴权 Token,通过云信控制台获取或调用服务端 API 生成。获取方式详见获取静态 Token
    option V2NIMLoginOption - 登录配置。静态 Token 登录可配置如下字段:
  • forceMode:是否强制登录
  • timeout:登录超时时间
  • retryCount:登录失败后重试次数
  • authType:鉴权方式,默认为 0 静态 Token 鉴权
  • syncLevel:数据同步模式,分为完全同步和基础数据同步。Web 端仅支持完全同步。
  • 示例代码:

    Android
    javaNIMClient.getService(V2NIMLoginService.class).login("account", "token", null, new V2NIMSuccessCallback<Void>() {
        @Override
        public void onSuccess(Void unused) {
            // TODO
        }
    },
        new V2NIMFailureCallback() {
        @Override
        public void onFailure(V2NIMError error) {
            int code = error.getCode();
            String desc = error.getDesc();
            // TODO
        }
    });
    
    iOS
    objective-c- (void)login
    {
        NSString *accountId = @"accountId";
        NSString *token = @"token";
        [[NIMSDK sharedSDK].v2LoginService login:accountId token:token
                option:nil
                  success:^{
            NSLog(@"login succ");
        }
                  failure:^(V2NIMError * _Nonnull error) {
            NSLog(@"login fail: error = %@", error);
        }];
    }
    
    macOS/Windows
    cppV2NIMLoginOption option;
    loginService.login(
        "accountId",
        "token",
        option,
        []() {
            // login succeeded
        },
        [](V2NIMError error) {
            // login failed, handle error
        });
    
    Web/uni-app/小程序
    typescripttry {
      await nim1.V2NIMLoginService.login("ACCOUNT_ID", "TOKEN", {
        "forceMode": false
      })  
    } catch (err) {
      // TODO failed, check code
      // console.log(err.code)
    }
    
    Harmony
    typescripttry {
    await nim.loginService.login("ACCOUNT_ID", "TOKEN", {
        forceMode: false
    } as V2NIMLoginOption)
    } catch (err) {
    // TODO failed, check code
    // console.log(err.code)
    }
    

动态 Token 登录

调用 login 方法登录 IM,鉴权方式为动态 Token 鉴权。您需要将 V2NIMLoginOption.authType 设置为 1,并设置获取动态 Token 回调 V2NIMLoginOption.tokenProvider

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

  • 登录部分参数说明:

    参数名称 类型 是否必填 默认值 描述
    accountId String - IM 为用户分配的唯一登录账号。通过云信控制台获取或调用服务端 API 注册。获取方式详见获取动态 Token
    token String - 静态鉴权 Token,可不填。
    如果您的应用启用了聊天室功能,并且采用非独立模式&静态 Token 登录方式,那么该参数必须设置,后续非独立模式的聊天室静态登录时会使用该静态 Token。
    option V2NIMLoginOption - 登录配置。动态 Token 登录可配置如下字段:
  • forceMode:是否强制登录
  • timeout:登录超时时间
  • retryCount:登录失败后重试次数
  • authType:鉴权方式,必须设置为 1
  • tokenProvider:获取动态 Token 回调,如果使用动态 Token 鉴权方式该字段必填。动态 Token 基于 App Key、App Secret 和 accountId,通过约定算法在服务端生成。该回调在登录连接完成、登录鉴权校验前触发。若函数执行有异常或返回非预期内容(非法字符串),则登录中止并报错。
  • syncLevel:数据同步模式,分为完全同步和基础数据同步
  • 如果设置了获取动态 Token 回调,但返回空值且未传入静态 Token,则返回 414 错误码,云信 IM 不做登录请求。
  • 若设置了获取动态 Token 回调且返回空值,但是已传入静态 Token,也会返回相关错误码。但 SDK 会持续与服务端进行重连,直到获取到动态 Token(不计入自动重连次数)。
  • 示例代码:

    Android
    javaV2NIMLoginOption option = new V2NIMLoginOption();
    //set auth type
    option.setAuthType(V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN);
    //set auth token provider
    option.setTokenProvider(new V2NIMTokenProvider() {
        @Override
        public String getToken(String accountId) {
            return "return your token with accountId";
        }
    });
    NIMClient.getService(V2NIMLoginService.class).login("accountId",null,option,new V2NIMSuccessCallback<Void>() {
            @Override
            public void onSuccess(Void unused) {
                // TODO
            }
        },
        new V2NIMFailureCallback() {
            @Override
            public void onFailure(V2NIMError error) {
                int code = error.getCode();
                String desc = error.getDesc();
                // TODO
            }
        });
    
    iOS
    objective-c@interface YourTokenProvider : NSObject <V2NIMTokenProvider>
    
    @end
    
    @implementation YourTokenProvider
    
    - (NSString *)getToken:(NSString *)accountId
    {
        return @"return your token with accountId";
    }
    
    @end
    
    - (void)loginWithDynamicToken
    {
        NSString *accountId = @"accountId";
        V2NIMLoginOption *option = [[V2NIMLoginOption alloc] init];
        option.authType = V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN; // setup type
        option.tokenProvider = [[YourTokenProvider alloc] init]; // setup provider
        [[NIMSDK sharedSDK].v2LoginService login:accountId token:nil
                option:option
                  success:^{
            NSLog(@"login succ");
        }
                  failure:^(V2NIMError * _Nonnull error) {
            NSLog(@"login fail: error = %@", error);
        }];
    }
    
    macOS/Windows
    cppauto& instance = V2NIMInstance::get();
    auto& loginService = instance.getLoginService();
    V2NIMLoginOption option;
    option.authType = V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN;
    option.tokenProvider = [](nstd::string accountId) {
        nstd::string token;
        // get token
        // ...
        return token;
    };
    loginService.login(
        "accountId",
        "",
        option,
        []() {
            // login succeeded
        },
        [](V2NIMError error) {
            // login failed, handle error
        });
    
    Web/uni-app/小程序
    typescripttry {
      await nim.V2NIMLoginService.login("ACCOUNT_ID", "", {
        "forceMode": false,
        "authType": 1, // V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN
        "tokenProvider": function(accountId) {
          return Promise.resolve('YOUR_DYNAMIC_TOKEN')
        }
      })  
    } catch (err) {
      // TODO failed, check code
      // console.log(err.code)
    }
    
    Harmony
    typescripttry {
    await nim.loginService.login("ACCOUNT_ID", "", {
        forceMode: false,
        authType: V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN, // 1, V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_DYNAMIC_TOKEN
        tokenProvider: ((accountId: string): Promise<string> | string => {
        return Promise.resolve('YOUR_DYNAMIC_TOKEN')
        }) as V2NIMTokenProvider
    } as V2NIMLoginOption)
    } catch (err) {
    // TODO failed, check code
    // console.log(err.code)
    }
    

通过第三方回调登录

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

  1. 通过第三方回调登录 IM,首先需要开通和配置第三方服务

  2. 如果您需要采用第三方服务器的动态登录扩展数据或动态 Token 进行鉴权,那么需要在调用 login 方法登录时将 V2NIMLoginOption.authType 设置为 2,并设置获取动态登录扩展数据 V2NIMLoginOption.loginExtensionProvider 回调和获取动态 Token 回调 V2NIMLoginOption.tokenProvider,SDK 会在登录过程中获取第三方回调的动态扩展数据和动态 Token。

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

  • 登录部分参数说明:

    参数名称 类型 是否必填 默认值 描述
    accountId String - IM 为用户分配的唯一登录账号。通过云信控制台获取或调用服务端 API 注册。
    token String - 静态鉴权 Token,可不填。
    如果您的应用启用了聊天室功能,并且采用非独立模式&静态 Token 登录方式,那么该参数必须设置,后续非独立模式的聊天室静态登录时会使用该静态 Token。
    option V2NIMLoginOption - 登录配置。动态 Token 登录可配置如下字段:
  • forceMode:是否强制登录
  • timeout:登录超时时间
  • retryCount:登录失败后重试次数
  • authType:鉴权方式,必须设置为 2
  • loginExtensionProvider:获取用户登录业务扩展数据回调,如果使用第三方回调鉴权方式,该字段必填。该回调在登录连接完成、登录鉴权校验前触发。若函数执行有异常或返回非预期内容(非法字符串),则登录中止并报错。
  • tokenProvider:获取动态 Token 回调,如果使用第三方回调鉴权方式,该字段用于第三方服务器的动态 Token 鉴权。
  • syncLevel:数据同步模式,分为完全同步和基础数据同步
  • 如果设置了获取动态登录扩展数据回调和获取动态 Token 回调,但都返回空值且未传入静态 Token,则返回 414 错误码,云信 IM 不做登录请求。
  • 若设置了获取动态登录扩展数据回调和获取动态 Token 回调且返回空值,但是已传入静态 Token,也会返回相关错误码。但 SDK 会持续与服务端进行重连,直到获取到动态登录扩展数据或动态 Token(不计入自动重连次数)。
  • 示例代码:

    以通过第三方动态登录扩展数据 V2NIMLoginOption.loginExtensionProvider 回调登录为例:

    Android
    javaV2NIMLoginOption option = new V2NIMLoginOption();
    // set auth type
    option.setAuthType(V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY);
    // set auth token provider
    option.setLoginExtensionProvider(new V2NIMLoginExtensionProvider() {
        @Override
        public String getLoginExtension(String accountId) {
            return "return your login extension with accountId";
        }
    });
    NIMClient.getService(V2NIMLoginService.class).login("accountId", "token", option, new V2NIMSuccessCallback<Void>() {
        @Override
        public void onSuccess(Void unused) {
            // TODO
        }
    }, new V2NIMFailureCallback() {
        @Override
        public void onFailure(V2NIMError error) {
            int code = error.getCode();
            String desc = error.getDesc();
            // TODO
        }
    });
    
    iOS
    objective-c@interface YourLoginExtensionProvider : NSObject <V2NIMLoginExtensionProvider>
    
    @end
    
    @implementation YourLoginExtensionProvider
    
    - (NSString *)getLoginExtension:(NSString *)accountId
    {
        return @"return your login extension with accountId";
    }
    
    @end
    
    - (void)loginWithThirdParty
    {
        NSString *accountId = @"accountId";
        NSString *token = @"token";
        V2NIMLoginOption *option = [[V2NIMLoginOption alloc] init];
        option.authType = V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY; // setup type
        option.loginExtensionProvider = [[YourLoginExtensionProvider alloc] init]; // setup provider
        [[NIMSDK sharedSDK].v2LoginService login:accountId token:token
                                          option:option
                                         success:^{
            NSLog(@"login succ");
        } failure:^(V2NIMError * _Nonnull error) {
            NSLog(@"login fail: error = %@", error);
        }];
    }
    
    macOS/Windows
    cppauto& instance = V2NIMInstance::get();
    auto& loginService = instance.getLoginService();
    V2NIMLoginOption option;
    option.authType = V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY;
    option.loginExtensionProvider = [](std::string accountId) {
        std::string loginExtension;
        // get login extension
        // ...
        return loginExtension;
    };
    loginService.login(
        "accountId",
        "",
        option,
        []() {
            // login succeeded
        },
        [](V2NIMError error) {
            // login failed, handle error
        });
    
    Web/uni-app/小程序
    typescripttry {
      await nim.V2NIMLoginService.login("ACCOUNT_ID", "", {
        "forceMode": false,
        "authType": 2, // V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY
        "loginExtensionProvider": function(accountId) {
          return Promise.resolve('YOUR_LOGIN_EXTENSION')
        }
      })  
    } catch (err) {
      // TODO failed, check code
      // console.log(err.code)
    }
    
    Harmony
    typescripttry {
    await nim.loginService.login("ACCOUNT_ID", "", {
        forceMode: false,
        authType: V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY, // 2, V2NIMLoginAuthType.V2NIM_LOGIN_AUTH_TYPE_THIRD_PARTY
        loginExtensionProvider: ((accountId: string): Promise<string> | string => {
        return Promise.resolve('YOUR_LOGIN_EXTENSION')
        }) as V2NIMLoginExtensionProvider
    } as V2NIMLoginOption)
    // success
    } catch (err) {
    // TODO failed, check code
    // console.log(err.code)
    }
    
    • 通过第三方回调登录,如果设置了获取第三方动态 Token 和登录扩展数据回调,但都返回空值且未传入静态 Token 和登录扩展数据(可能第三方服务器设置了动态时间),则直接返回 414 错误码,云信 IM 内部不做登录请求。
    • 若设置了获取第三方动态 Token 和登录扩展数据回调且返回空值,但是已传入静态 Token,也会返回相关错误码,但会持续与服务端进行重连,直到动态 Token 传入(不计入自动重连次数)。
  1. 在服务端发起登录相关回调请求,由第三方服务器进行鉴权并判定 IM 登录事件是否放行通过。

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

(可选)步骤4:主动查询登录状态

通过 getLoginStatus 方法主动查询当前账号是否处于登录状态。

返回当前用户的登录的状态枚举值说明,请参见 IM 登录最佳实践的获取登录状态

Android
javaV2NIMLoginStatus status =  NIMClient.getService(V2NIMLoginService.class).getLoginStatus();
iOS
objective-c- (void)printLoginStatus:(V2NIMLoginStatus)status
{
    switch (status) {
        case V2NIM_LOGIN_STATUS_LOGOUT:
            NSLog(@"login status = logout");
            break;
        case V2NIM_LOGIN_STATUS_LOGINING:
            NSLog(@"login status = logining");
            break;
        case V2NIM_LOGIN_STATUS_LOGINED:
            NSLog(@"login status = logined");
            break;
        default:
            NSLog(@"login status = %ld", status);
    }
}

V2NIMLoginStatus status = [[[NIMSDK sharedSDK] v2LoginService] getLoginStatus];
macOS/Windows
C++auto loginStatus = loginService.getLoginStatus();
Web/uni-app/小程序
typescriptconst loginStatus = nim.V2NIMLoginService.getLoginStatus()
Harmony
typescriptconst loginStatus = nim.loginService.getLoginStatus()

登出 IM

一般情况下,如果您的应用生命周期跟 NIM SDK 生命周期一致,用户在退出应用前可以不登出,直接退出即可。

但某些特殊场景,例如用户仅在进入特定界面后才调用 NIM SDK 的能力,退出界面后不再调用,此时需要调用 NIM SDK 的登出接口注销 IM 登录。 登出后,用户将不再接收 IM 的消息。

用户在登出应用/注销自己的账号时需要调用 logout 方法登出 IM,该方法没有回调。

示例代码:

Android
java// 请勿在 Activity 的 `onDestroy` 中调用 `logout` 方法
NIMClient.getService(V2NIMLoginService.class).logout(new V2NIMSuccessCallback(){
     @Override
     public void onSuccess(){
         // TODO     
     }    
}, new V2NIMFailueCallback<V2NIMError>(){
     @Override
     public void onFailure(V2NIMError error){
         int code = error.code;
         String desc = error.desc;
         // TODO
     }   
});
iOS
objective-c- (void)logout
{
    [[NIMSDK sharedSDK].v2LoginService logout:^{
        NSLog(@"logout succ");
    } failure:^(V2NIMError * _Nonnull error) {
        NSLog(@"logout fail: error = %@", error);
    }];
}
macOS/Windows
C++loginService.logout(
    []() {
        // logout succeeded
    },
    [](V2NIMError error) {
        // logout failed, handle error
    });
Web/uni-app/小程序
typescripttry {
  await nim.V2NIMLoginService.logout()  
} catch (err) {
  // TODO failed, check code
  // console.log(err.code)
}
Harmony
typescripttry {
  await nim.loginService.logout()  
} catch (err) {
  // TODO failed, check code
  // console.log(err.code)
}

请勿频繁调用登录、登出方法,其间隔至少要大于 3 秒。

相关信息

相关文档

断线重连机制

SDK 提供了自动重连机制,当网络问题导致连接断开或超时,SDK 会自动重新建立与云信服务端的连接并重新登录,您无需主动重复登录。您可以调用 addLoginDetailListener 方法注册登录连接状态监听器,通过 onConnectStatus 回调监听重连后的登录状态变更。

常见问题

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

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

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

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

如何处理登录请求被拒绝问题?

若您开启了应用标识安全验证,需要在将列表中写入允许的客户端应用标识。当请求登录的客户端应用标识不在列表中时,登录请求将被拒绝。

在控制台首页应用管理选择应用进入应用配置页面,顶部选择标识管理页签,添加对应的客户端应用标识。

应用标识管理.png

此文档是否对你有帮助?
有帮助
去反馈
  • 支持平台
  • 技术原理
  • 账号登录流程
  • 登录方式
  • 前提条件
  • 配置 IM 登录策略
  • 实现登录 IM
  • 步骤1:准备 Token
  • 获取静态 Token
  • 获取动态 Token
  • 获取动态登录扩展数据
  • 步骤2:注册登录相关事件监听
  • 1. 注册登录状态相关监听
  • 2. 注册登录连接状态监听
  • 步骤3:登录 IM
  • 静态 Token 登录
  • 动态 Token 登录
  • 通过第三方回调登录
  • (可选)步骤4:主动查询登录状态
  • 登出 IM
  • 相关信息
  • 相关文档
  • 断线重连机制
  • 常见问题
  • 如何根据产品形态选择 IM 登录方式?
  • 如何处理登录请求被拒绝问题?