实时音视频
  • iOS
  • Android : Java
  • macOS
  • Windows
  • HarmonyOS
  • Linux
  • Web
  • 小程序
  • Flutter
  • Electron
  • Unity3D
  • uni-app
  • React Native
  • Cocos2D
  • 产品简介
  • 下载
  • 体验 App
  • 快速开始
    • 跑通示例源码
    • 集成 SDK
    • 实现视频通话
    • 实时音视频 SDK 与实时语音 SDK 差异
    • 场景化音视频配置
  • 基础功能
  • 进阶功能
  • 最佳实践
  • 常见错误码
  • 服务端 API
  • 客户端 API
  • 常见问题

使用 Token 鉴权

更新时间:2022-09-22 15:35

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 流程概述

使用 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 再将校验的结果直接返回给开发者客户端,没有权限的客户端将登录失败。

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

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

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

String roomID = "xxx" // 要登录的房间ID
ZegoUser user = new ZegoUser("xxxx");
ZegoRoomConfig config = new ZegoRoomConfig();
config.token = "xxxxxxxxxx"; // 请求开发者服务端获取
engine.loginRoom(roomID, user, config);

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

String token = getToken(); // 重新请求开发者服务端获取 Token;
engine.renewToken(roomID, token);

4.4 Token 过期处理机制

在 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:
      • 已登录的用户不会被踢出房间。
      • 当前已成功的推拉流不受影响,但是会影响用户的下一次推拉流操作。

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

@Override
public void onRoomTokenWillExpire(String roomID, int remainTimeInSecond){
    String token = getToken(); // 重新请求开发者服务端获取 Token;
    engine.renewToken(roomID, 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 相关文档

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