多端登录管理

更新时间:2025-12-02 02:09:43下载pdf

功能概述

涂鸦智能 iOS SDK 提供了多端登录管理功能,允许用户查看和管理当前账号在所有设备上的登录状态。用户可以通过账号验证或密码验证的方式,安全地终止其他设备上的登录会话,确保账号安全。

接入准备

  1. 首先,确保项目已依赖了最新版本的涂鸦全屋智能 SDK。

  2. 然后,导入所需框架。

     import ThingSmartHomeKit
    

ThingSmartUser 多端登录管理接口详解

获取登录设备列表

接口说明

获取当前账号在所有设备上的登录列表。

- (void)getLoginTerminalListWithSuccess:(nonnull void(^)( NSArray <ThingSmartLoginTerminalModel *> * __nullable))success
                                failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
success 成功回调,返回 ThingSmartLoginTerminalModel 数组
failure 失败回调,返回错误信息

ThingSmartLoginTerminalModel 属性说明

属性 类型 说明
terminalId NSString 设备唯一标识符
platform NSString 设备平台名称
os NSString 操作系统类型
loginTime NSTimeInterval 登录时间戳

示例代码

Swift:

ThingSmartUser.sharedInstance().getLoginTerminalList { terminals in
    self.loginTerminals = terminals ?? []
    self.tableView.reloadData()
} failure: { error in
    print("Failed to get login terminals: \(error?.localizedDescription ?? "Unknown error")")
    self.showErrorAlert(message: error?.localizedDescription ?? "Unknown error")
}

获取设备登出校验码

接口说明

通过账号验证或密码验证获取设备登出验证码,用于后续终止设备会话。

支持两种验证方式:验证码密码

- (void)getLogoutCodeByAuthorizingAccount:(ThingSmartAccountAuthenticationRequestModel *)requestModel
                                success:(nullable void(^)(ThingSmartAccountAuthenticationModel *))success
                                failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
requestModel 验证请求模型,包含账号信息和验证类型
success 成功回调,返回包含登出验证码的模型
failure 失败回调,返回错误信息

ThingSmartAccountAuthenticationRequestModel 属性说明

属性 类型 说明
countryCode NSString 国家代码,如 “86”
userName NSString 用户名(邮箱或手机号,格式要求见下方说明)
authCode NSString 验证码(验证码验证时必填,6 位数字)
password NSString 密码(密码验证时必填)
accountType ThingSmartAuthenticationAccountType 账号类型(.email 或 .phone)
verifyType ThingSmartAuthenticationVerifyType 验证类型(.authCode 或 .password)
ifencrypt NSInteger 是否加密(密码验证时设置为 1)

ThingSmartAccountAuthenticationModel 属性说明

属性 类型 说明
logoutCode NSString 登出验证码,用于终止设备会话

验证方式一:验证码验证

适用场景

  • 用户已绑定邮箱或手机号。
  • 可以接收验证码的用户。

入参要求

参数 说明
countryCode 用户的国家代码 如 “86”
userName 邮箱或手机号 邮箱:完整邮箱地址
手机号:去掉国家代码和 “-” 的纯数字
authCode 6 位数字验证码 必填,通过 sendVerifyCode 接口获取
password 不设置 验证码验证时不需要
accountType .email 或 .phone 根据 userName 类型设置
verifyType .authCode 固定值
ifencrypt 不设置 验证码验证时不需要

userName 格式说明

  • 邮箱格式user@example.com
  • 手机号格式
    • 原始格式:86-13800138000
    • 处理后格式:13800138000(去掉国家代码和 “-”)

验证方式二:密码验证

适用场景

  • 手机号注册且没有绑定邮箱的用户。
  • 用户记得登录密码。

入参要求

参数 说明
countryCode 用户的国家代码 如 “86”
userName 手机号 去掉国家代码和 “-” 的纯数字
authCode 不设置 密码验证时不需要
password 用户登录密码 必填,原始密码
accountType .phone 固定值,密码验证仅支持手机号
verifyType .password 固定值
ifencrypt 1 固定值,表示密码加密传输

userName 格式说明

  • 原始格式86-13800138000
  • 处理后格式13800138000(去掉国家代码和 “-”)

示例代码

  • 验证码验证示例(Swift):

    // 方式一:验证码验证
    // 发送验证码
    ThingSmartUser.sharedInstance().sendVerifyCode(
        withUserName: accountText,
        region: ThingSmartUser.sharedInstance().regionCode,
        countryCode: ThingSmartUser.sharedInstance().countryCode,
        type: 10
    ) { [weak self] in
        
    } failure: { [weak self] error in
        
    }
    
    let requestModel = ThingSmartAccountAuthenticationRequestModel()
    requestModel.countryCode = ThingSmartUser.sharedInstance().countryCode
    
    // 根据账号类型设置 userName
    let email = ThingSmartUser.sharedInstance().email
    let phoneNumber = ThingSmartUser.sharedInstance().phoneNumber
    
    if !email.isEmpty {
        // 邮箱验证
        requestModel.userName = email
        requestModel.accountType = .email
    } else {
        // 手机号验证 - 去掉国家代码和"-"
        var phone = phoneNumber
        if phone.contains("-") {
            phone = phone.components(separatedBy: "-").last ?? phone
        }
        requestModel.userName = phone
        requestModel.accountType = .phone
    }
    
    requestModel.authCode = "123456" // 6位验证码
    requestModel.verifyType = .authCode
    
    ThingSmartUser.sharedInstance().getLogoutCode(
        byAuthorizingAccount: requestModel,
        success: { authModel in
            let logoutCode = authModel.logoutCode
            self.logoutCode = logoutCode
            print("Logout code obtained: \(logoutCode ?? "")")
        },
        failure: { error in
            print("Failed to get logout code: \(error?.localizedDescription ?? "Unknown error")")
        }
    )
    
  • 密码验证示例(Swift):

    // 方式二:密码验证
    let requestModel = ThingSmartAccountAuthenticationRequestModel()
    requestModel.countryCode = ThingSmartUser.sharedInstance().countryCode
    
    // 处理手机号格式 - 去掉国家代码和"-"
    let phoneNumber = ThingSmartUser.sharedInstance().phoneNumber
    var phone = phoneNumber
    if phone.contains("-") {
        phone = phone.components(separatedBy: "-").last ?? phone
    }
    requestModel.userName = phone
    
    requestModel.password = "userPassword" // 用户登录密码
    requestModel.accountType = .phone // 固定为手机号
    requestModel.verifyType = .password
    requestModel.ifencrypt = 1 // 密码加密传输
    
    ThingSmartUser.sharedInstance().getLogoutCode(
        byAuthorizingAccount: requestModel,
        success: { authModel in
            let logoutCode = authModel.logoutCode
            self.logoutCode = logoutCode
            print("Logout code obtained: \(logoutCode ?? "")")
        },
        failure: { error in
            print("Failed to get logout code: \(error?.localizedDescription ?? "Unknown error")")
        }
    )
    

终止设备会话

接口说明

使用登出验证码强制终止指定设备上的登录会话。

- (void)terminateSessionOnDevice:(NSString *)terminalId
                      logoutCode:(NSString *)logoutCode
                         success:(nullable ThingSuccessBOOL)success
                         failure:(nullable ThingFailureError)failure;

参数说明

参数 说明
terminalId 设备唯一标识符
logoutCode 登出验证码(从 getLogoutCodeByAuthorizingAccount 获取)
success 成功回调,返回 BOOL 值表示是否成功终止会话
failure 失败回调,返回错误信息

示例代码

Swift:

ThingSmartUser.sharedInstance().terminateSession(
    onDevice: terminal.terminalId,
    logoutCode: self.logoutCode
) { success in
    if success {
        print("Device session terminated successfully")
        // 从列表中移除设备
        self.loginTerminals.remove(at: indexPath.row)
        self.tableView.deleteRows(at: [indexPath], with: .fade)
    } else {
        print("Failed to terminate device session")
        self.showErrorAlert(message: "Failed to terminate device session")
    }
} failure: { error in
    print("Failed to terminate device session: \(error?.localizedDescription ?? "Unknown error")")
    self.showErrorAlert(message: error?.localizedDescription ?? "Unknown error")
}

监听账号退出通知

当用户在其他设备上被登出时,当前设备需要监听退出通知并处理相应的逻辑。

Swift:

// 添加通知监听
NotificationCenter.default.addObserver(
    self,
    selector: #selector(handleUserLogout(_:)),
    name: NSNotification.Name.ThingSmartUserNotificationUserSessionInvalid,
    object: nil
)

// 处理退出通知
@objc private func handleUserLogout(_ notification: Notification) {
    DispatchQueue.main.async {
        // 显示退出提示
        let alert = UIAlertController(
            title: "账号已退出",
            message: "您的账号已在其他设备上退出,请重新登录",
            preferredStyle: .alert
        )
        
        let okAction = UIAlertAction(title: "确定", style: .default) { _ in
            // 跳转到登录页面
            self.navigationController?.popToRootViewController(animated: true)
        }
        
        alert.addAction(okAction)
        self.present(alert, animated: true)
    }
}

// 移除通知监听
deinit {
    NotificationCenter.default.removeObserver(self)
}

使用流程

基本流程

  1. 调用 getLoginTerminalList 获取登录设备列表。
  2. 用户选择要登出的设备。
  3. 进行安全验证(账号验证码验证或密码验证)。
  4. 调用 getLogoutCodeByAuthorizingAccount 获取登出验证码。
  5. 调用 terminateSessionOnDevice 终止设备会话。

账号验证码验证流程

  1. 用户输入验证码。
  2. 调用 sendVerifyCode 发送验证码(如需要)。
  3. 调用 getLogoutCodeByAuthorizingAccount 进行验证码验证。
  4. 获取登出验证码后可以终止设备会话。

密码验证流程

  1. 用户输入登录密码。
  2. 调用 getLogoutCodeByAuthorizingAccount 进行密码验证。
  3. 获取登出验证码后可以终止设备会话。

注意事项

验证方式选择

  • 验证码验证:适用于已绑定邮箱或手机号的用户,需要先调用 sendVerifyCode 发送验证码。
  • 密码验证:仅适用于手机号注册且没有绑定邮箱的用户。

userName 格式要求

  • 邮箱格式:完整邮箱地址,如 user@example.com
  • 手机号格式:去掉国家代码和 “-” 后的纯数字,如 13800138000

参数设置要求

  • 验证码验证:必须设置 authCode,不需要设置 passwordifencrypt
  • 密码验证:必须设置 passwordifencrypt=1,不需要设置 authCode

登出码有效期

获取的登出验证码有时效性,建议及时使用。

错误处理

所有接口调用都应该处理失败情况,给用户适当的错误提示。

UI 更新

网络请求的回调中更新 UI 时,确保在主线程执行。