实时语音
  • iOS
  • Android
  • macOS : Objective-C
  • Windows
  • Linux
  • Web
  • 小程序
  • Flutter
  • Electron
  • Unity3D
  • uni-app
  • React Native
  • Cocos Creator
  • 产品简介
    • 概述
    • 产品功能
    • 发布日志
    • 计费说明
    • 限制说明
    • 升级指南
  • 下载
  • 快速开始
    • 跑通示例源码
    • 集成 SDK
    • 实现音频通话
    • 实时音视频 SDK 与实时语音 SDK 差异
    • 场景化音视频配置
  • 基础功能
  • 进阶功能
  • 常见错误码
  • 服务端 API
  • 客户端 API
  • 常见问题

使用 Token 鉴权

更新时间:2022-12-09 21:27

1 功能介绍

鉴权是指验证用户是否拥有访问系统的权限,来避免因权限控制缺失或操作不当引发的安全风险问题,ZEGO 通过 Token(包括基础鉴权 Token 和权限认证 Token) 对用户进行鉴权。

鉴权方式 描述 应用场景
基础鉴权 Token 开发者在登录房间时必须带上 Token 参数,来验证用户的合法性。 基础鉴权 Token 为 Token 的基本能力,用于业务的简单权限验证场景,绝大多数情况下生成该 Token 即可。
权限认证 Token 为了进一步提高安全性开放了房间 ID 和推流 ID 这两个权限位,可以验证登录房间的 ID 和推流 ID。 房间 ID 和推流 ID 权限位的一般使用场景如下:
  • 房间有普通房间和会员房间的区别,需要控制非会员用户登录会员房间。
  • 语聊房或秀场直播中,需要控制推流用户和麦上用户的一致,防止“幽灵麦”现象,即在房间里听到了非麦上用户声音的情况。
  • 狼人杀等发言游戏,需要防止应用被黑客破解之后,黑客可以使用其他用户 ID 登录同一房间,获取到游戏进行的信息进行作弊,影响正常用户的游戏体验。

2 前提条件

  • 基础鉴权 Token 默认开通,权限认证 Token(即房间 ID 和推流 ID 权限位)请联系 ZEGO 技术支持开通。
  • 已在项目中集成 ZEGO Express SDK(2.17.0 及以上版本),实现基本的实时音视频功能,请参考 快速开始 - 集成快速开始 - 实现流程

若您集成的是 2.17.0 之前版本的 ZEGO Express SDK(使用 AppSign 鉴权),现在想升级到 2.17.0 版本且使用 Token 鉴权,可以通过 如何从 AppSign 鉴权升级为 Token 鉴权 文档了解 AppSign 鉴权和 Token 鉴权更多信息。

3 流程概述

3.1 房间模块

使用 Token 鉴权时,需要开发者先生成 Token,您再携带 Token 登录房间,ZEGO 服务端对带着 Token 的用户进行校验。

以使用 Token 判断用户是否能登录房间为例介绍使用流程,如下图:

token_uml

  1. 开发者客户端发起申请 Token 的请求。
  2. 在开发者的服务端上生成 Token,并返回给开发者客户端。
  3. 开发者客户端携带申请到的 Token 和 userID、roomID 信息,登录对应的房间。
  4. ZEGO SDK 会自动将 Token 发送到 ZEGO 服务端进行校验。
  5. ZEGO 服务端会将校验结果返回给 ZEGO SDK。
  6. ZEGO SDK 再将校验的结果直接返回给开发者客户端,没有权限的客户端将登录失败。

3.2 范围场景模块

使用 Token 鉴权时,需要开发者先生成 Token,您再携带 Token 登录场景,ZEGO 服务端对带着 Token 的用户进行校验。

以使用 Token 判断用户是否能登录场景为例介绍使用流程,如下图:

token_rangescene_uml

  1. 开发者客户端发起申请 Token 的请求。
  2. 在开发者的服务端上生成 Token,并返回给开发者客户端。
  3. 开发者客户端携带申请到的 Token 和 userID、sceneID 信息,登录对应的场景。
  4. ZEGO SDK 会自动将 Token 发送到 ZEGO 服务端进行校验。
  5. ZEGO 服务端会将校验结果返回给 ZEGO SDK。
  6. ZEGO SDK 再将校验的结果直接返回给开发者客户端,没有权限的客户端将登录失败。

4 基础鉴权 Token 的生成与使用

本节将详细介绍开发者如何生成基础鉴权 Token、如何使用 Token 和 Token 过期时的处理方式。

4.1 获取 AppID 和 ServerSecret

生成 Token 需要开发者项目的唯一标识 AppID 和密钥 ServerSecret,请参考 控制台 - 项目管理 中的 “项目信息”获取。

开发者获得项目的 AppID 和 ServerSecret 信息后,根据实际业务需求,即可在自己的服务端生成 Token。开发者客户端向开发者服务端发送申请 Token 请求,由开发者服务端生成 Token 后返回给到对应客户端。

4.2 生成基础鉴权 Token

基础鉴权 Token:用于业务的简单权限验证的场景,生成基础鉴权 Token 时,“payload” 字段传空。

Token 临时获取方式:为方便开发者调试,ZEGO 控制台 提供生成临时 Token 的功能,开发者可直接获取临时 Token 来使用,详情请参考 控制台 - 开发辅助。但是在开发者自己的线上环境中,一定要通过自己的服务端生成 Token。

ZEGO 在 GitHub/Gitee 提供了一个开源的 zego_server_assistant 插件,请使用插件中的 “token04” 版本来生成 Token。插件支持 Go、C++、Java、Objective-C、Python、PHP、.NET、Node.js 语言:

语言 支持版本 关键函数 代码库地址 示例代码地址
基础鉴权 Token 权限认证 Token
Go
Go 1.14.15 或以上版本
GenerateToken04
C++
C++ 11 或以上版本
GenerateToken04
Java
Java 1.8 或以上版本
generateToken04
Python
Python 3.6.8 或以上版本
generate_token04
PHP
PHP 7.0 或以上版本
generateToken04
.NET
.NET Framework 3.5 或以上版本
GenerateToken04
Node.js
Node.js 8 或以上版本
generateToken04

以 Go 语言为例,开发者可参考以下步骤使用 zego_server_assistant 生成 Token:

  1. 将 “go/zegoserverassistant” 目录拷贝到开发者的服务端项目中。
  2. 使用命令 import zsa "your-project-go-mod-path/zegoserverassistant" 引入插件,需要将 “your-project-go-mod-path” 替换为开发者自己的项目名称。
  3. 调用插件提供的 GenerateToken 方法生成 Token,生成基础鉴权 Token 示例代码如下:
package main

import (
    "fmt"
    "github.com/zegoim/zego_server_assistant/token/go/src/token04"
)

/*
基础鉴权token生成示例代码
*/

func main() {
    var appId uint32 = 1                               // Zego派发的数字ID, 各个开发者的唯一标识
    userId := "demo"                                   // 用户 ID
    serverSecret := "fa94dd0f974cf2e293728a526b028271" // 在获取 token 时进行 AES 加密的密钥
    var effectiveTimeInSeconds int64 = 3600            // token 的有效时长,单位:秒
    var payload string = ""                            // token业务认证扩展,基础鉴权token此处填空

    //生成token
    token, err := token04.GenerateToken04(appId, userId, serverSecret, effectiveTimeInSeconds, payload)
    if err != nil {
    fmt.Println(err)
    return
    }
    fmt.Println(token)
}

4.3 使用 Token

4.3.1 房间模块

用户携带获取到的 Token 和 user、roomID 信息,登录对应的房间。

调用 loginRoom 接口登录房间时使用的 userID,必须和 “4.2 生成基础鉴权 Token” 时使用的 userID 保持一致。

NSString *roomID = @"xxx"; // 要登录的房间 ID
ZegoUser *user = [ZegoUser userWithUserID:@"xxxx"];
ZegoRoomConfig *config = [[ZegoRoomConfig alloc] init];
config.token = @"xxxxxxxx"; // 请求开发者服务端获取

[[ZegoExpressEngine sharedEngine] loginRoom:roomID user:user config:config];

如果开发者需要在用户登录房间后修改用户的推流权限,也可以调用 renewToken 接口更新权限,更新后会影响下一次推流的权限,之前已经成功的推流不受影响。

NSString *token = [MyToken getToken]; // 重新请求开发者服务端获取 Token
[[ZegoExpressEngine sharedEngine] renewToken:token roomID:roomID];

4.3.2 范围场景模块

用户携带获取到的 Token 和 user、sceneID 信息,登录对应的场景。

调用 loginScene 接口登录场景时使用的 userID,必须和 “4.2 生成基础鉴权 Token” 时使用的 userID 保持一致。

long long sceneID = 123; // 要登录的场景 ID
ZegoUser *user = [ZegoUser userWithUserID:@"xxxx"];
ZegoSceneParam *param = [[ZegoSceneParam alloc] init];
param.sceneID = sceneID;
param.user = user;
param.token = @"xxxxxxxx"; // 请求开发者服务端获取

[rangeScene loginScene:param callback:^(int errorCode, ZegoSceneConfig * _Nonnull config) {}];

4.4 Token 过期时的处理方式

Token 过期可能导致推拉流异常等问题,请严格按照以下说明,及时处理过期 Token。

4.4.1 房间模块

在 Token 过期前 30 秒,SDK 会通过 onRoomTokenWillExpire 回调发出通知。

收到该回调后,开发者需要从自己的服务端获取新的有效 Token,并调用 SDK 提供的 renewToken 接口更新 Token。若未处理,不同版本对 Token 过期的处理机制有所不同:

  • 若您接入的是 2.8.0 ~ 2.12.0 版本的 ZEGO Express SDK,此时如果未更新 Token,则在权限位过期时:
    • 已登录的用户不会被踢出房间。
    • 当前已成功的推拉流不受影响,但是会影响用户的下一次推拉流操作。
  • 若您接入的是 2.13.0 及以上版本的 ZEGO Express SDK:
    • 可以联系 ZEGO 技术支持额外配置权限位过期管理机制,此时如果未更新 Token,则当权限位过期时:
      • 已登录的用户会被踢出房间,且无法再登录房间。
      • 当前已成功的推流会被停止,也无法进行下一次推流。
    • 若未联系 ZEGO 技术支持额外配置权限位过期管理机制,此时如果未更新 Token:
      • 已登录的用户不会被踢出房间。
      • 当前已成功的推拉流不受影响,但是会影响用户的下一次推拉流操作。

若开启了登录权限校验,用户登录房间时必须主动传入新的 Token。

- (void)onRoomTokenWillExpire:(int)remainTimeInSecond roomID:(NSString *)roomID {
    NSString *token = [MyToken getToken]; // 重新请求开发者服务端获取 Token

    [[ZegoExpressEngine sharedEngine] renewToken:token roomID:roomID];
}

4.4.2 范围场景模块

在 Token 过期前 30 秒,SDK 会通过 tokenWillExpire 回调发出通知。

收到该回调后,开发者需要从自己的服务端获取新的有效 Token,并调用 SDK 提供的 ZegoRangeScene.renewToken 接口更新 Token。若未处理,Token 过期的处理机制如下:

  • 已登录的用户不会被踢出场景。
  • 当前已成功的推拉流不受影响,但是会影响用户的下一次推拉流操作。

若开启了登录权限校验,用户登录场景时必须主动传入新的 Token。

- (void)rangeScene:(ZegoRangeScene *)rangeScene tokenWillExpire:(int)remainTimeInSecond {
    NSString *token = [MyToken getToken]; // 重新请求开发者服务端获取 Token
    // 请切换线程调用 renewToken
    [rangeScene renewToken:token];
}

5 进阶功能

5.1 生成权限认证 Token

权限认证 Token:为了进一步提高安全性,开放房间 ID 和推流 ID 这两个权限位,可以验证登录房间的 ID 和推流 ID,此时 “payload” 字段需要按照规则生成,权限位校验规则如下:

  • 只校验登录权限:登录时校验权限,推流时不校验权限。
  • 校验推流权限:推流时校验权限,登录时不校验权限。
  • 同时校验登录和推流权限:登录和推流时均校验权限。

ZEGO 在 GitHub/Gitee 提供了一个开源的 zego_server_assistant 插件,支持使用 Go、C++、Java、Objective-C、Python、PHP、.NET、Node.js 语言生成 Token。请查看 4.2 生成基础鉴权 Token 获取插件。

以 Go 语言为例,开发者可参考以下步骤使用 zego_server_assistant 生成 Token:

  1. 将 “go/zegoserverassistant” 目录拷贝到开发者的服务端项目中。
  2. 使用命令 import zsa "your-project-go-mod-path/zegoserverassistant" 引入插件,需要将 “your-project-go-mod-path” 替换为开发者自己的项目名称。
  3. 调用插件提供的 GenerateToken 方法生成 Token,生成权限认证 Token 的示例代码如下:

生成权限认证 Token 时必须传入 “RoomId”。

package main

import (
    "encoding/json"
    "fmt"
    "github.com/zegoim/zego_server_assistant/token/go/src/token04"
)

/*
权限认证token生成示例代码
*/

//token业务扩展:权限认证属性
type RtcRoomPayLoad struct {
    RoomId       string      `json:"room_id"`        //房间 id(必填);用于对接口的房间 id 进行强验证
    Privilege    map[int]int `json:"privilege"`      //权限位开关列表;用于对接口的操作权限进行强验证
    StreamIdList []string    `json:"stream_id_list"` //流列表;用于对接口的流 id 进行强验证;允许为空,如果为空,则不对流 id 验证
}

func main() {
    var appId uint32 = 1                               // Zego派发的数字ID, 各个开发者的唯一标识
    roomId := "demo"                                   // 房间 ID
    userId := "demo"                                   // 用户 ID
    serverSecret := "fa94dd0f974cf2e293728a526b028271" // 在获取 token 时进行 AES 加密的密钥
    var effectiveTimeInSeconds int64 = 3600            // token 的有效时长,单位:秒

    //请参考 github.com/zegoim/zego_server_assistant/token/go/src/token04/token04.go 定义
    ////权限位定义
    //const (
    //    PrivilegeKeyLogin   = 1 // 登录权限位认证
    //    PrivilegeKeyPublish = 2 // 推流权限位认证
    //)

    ////权限开关定义
    //const (
    //    PrivilegeEnable     = 1 // 有权限
    //    PrivilegeDisable    = 0 // 无权限
    //)

    //业务权限认证配置,可以配置多个权限位
    privilege := make(map[int]int)
    privilege[token04.PrivilegeKeyLogin] = token04.PrivilegeEnable    // 有房间登录权限
    privilege[token04.PrivilegeKeyPublish] = token04.PrivilegeDisable // 无推流权限

    //token业务扩展配置
    payloadData := &RtcRoomPayLoad{
    RoomId:       roomId,
    Privilege:    privilege,
    StreamIdList: nil,
    }

    payload, err := json.Marshal(payloadData)
    if err != nil {
    fmt.Println(err)
    return
    }

    //生成token
    token, err := token04.GenerateToken04(appId, userId, serverSecret, effectiveTimeInSeconds, string(payload))
    if err != nil {
    fmt.Println(err)
    return
}
    fmt.Println(token)
}

运行生成 Token 的 Java 源码时,如果出现 “java.security.InvalidKeyException:illegal Key Size” 异常提示,请参考 相关常见问题文档 解决。

  1. 如需使用权限认证 token,请参考 4.3 使用 Token
  2. 若 Token 过期,请参考 4.4 Token 过期时的处理方式 进行处理。

5.2 客户端生成 Token(不推荐)

若您在开发过程中还无法通过服务端下发 Token 时,可以先使用客户端代码生成 Token,待服务端开发完后,再完成对接。

  • App 上线时,切勿在客户端生成 Token,否则您的 ServerSecret 将暴露在风险中。
  • 为保证安全性,强烈推荐您使用服务端生成 Token,否则会存在 ServerSecret 被窃取的风险。

zego_server_assistant 插件中用于客户端生成 Token 的各语言参考信息如下:

语言 支持版本 关键函数 具体地址
C++
C++ 11 或以上版本
GenerateToken04
Java
Java 1.8 或以上版本
generateToken04
Objective-C
-
GenerateToken04

如需使用客户端生成 Token,请参考 4.3 使用 Token

若 Token 过期,请参考 4.4 Token 过期时的处理方式 进行处理。

6 API 参考

方法 描述
loginRoom 登录房间
renewToken 更新 Token
onRoomTokenWillExpire Token 过期回调

7 相关文档

如何防止音视频互动中的幽灵麦或炸房的现象?