すべてのプロダクト
Search
ドキュメントセンター

ApsaraVideo Live:トークンベース認証の実装

最終更新日:Dec 25, 2025

トークンは、ID を認証し、不正なアクセスからクラウドサービスを保護するためのセキュリティ認証情報です。ApsaraVideo Real-time Communication (ARTC) では、アプリケーションサーバーがトークンを生成し、クライアントに送信する役割を担います。クライアントサイドの ARTC SDK は、そのトークンを使用してチャンネルに参加します。提供されたトークンの認証に成功した場合にのみ、アクセスが許可されます。

前提条件

  • Alibaba Cloud アカウントが作成され、ApsaraVideo Live が有効化されていること。

  • ARTC アプリケーションが作成され、AppID と AppKey が取得されていること。

サンプルコード

サーバーサイドでのトークン生成 (推奨)

ApsaraVideo Live は、Go、Java、Python など、複数の言語に対応したトークン生成のサンプルコードを提供しています。詳細は、GitHub リポジトリをご参照ください。

クライアントサイドでのトークン生成 (開発およびテスト用)

重要

トークンの生成には AppKey が必要です。クライアントに AppKey をハードコーディングすると、**セキュリティリスクが生じます**。本番環境では、**ビジネスサーバーでトークンを生成し、クライアントに送信してください**。

開発およびテスト段階で、独自のサーバーサイドでのトークン生成がまだ実装されていない場合は、APIExample のサンプルコードを使用して一時的なトークンを生成できます。サンプルコードは次のとおりです。

AndroidAndroid/ARTCExample/KeyCenter/src/main/java/com/aliyun/artc/api/keycenter/ARTCTokenHelper.java

iOSiOS/ARTCExample/Common/ARTCTokenHelper.swift

トークンを使用したチャンネルへの参加

説明

すべてのライブアプリケーションおよび本番アプリケーションでは、**トークンはサーバーで生成し、クライアントに渡す必要があります**。以下の例にあるクライアントサイドでのトークン生成メソッドは安全ではなく、デバッグおよびデモンストレーション目的でのみ使用してください。

AndroidAndroid/ARTCExample/QuickStart/src/main/java/com/aliyun/artc/api/quickstart/TokenGenerate/TokenGenerateActivity.java
iOSiOS/ARTCExample/QuickStart/TokenGenerate/TokenGenerateVC.swift

仕組み

手順

  1. クライアントはアプリケーションサーバーにトークンをリクエストします。アプリケーションサーバーは、事前に定義されたルールに従ってトークンを生成し、クライアントに返します。

  2. クライアントは、受信したトークンを appIdchannelIduserId などの他の必須情報とともに使用して、指定されたチャンネルへの参加をリクエストします。

  3. ARTC サーバーはトークンを検証し、検証が成功するとクライアントのチャンネルへの参加を許可します。

トークン生成方式

次の表に、トークン生成に使用するフィールドを示します。

フィールド

説明

AppID

コンソールでアプリケーションを作成した後に自動的に生成される ARTC のアプリケーション ID とキーです。詳細については、「開発パラメーターの取得」をご参照ください。

AppKey

ChannelID

カスタムチャンネル ID です。文字列である必要があり、数字、文字、ハイフン (-)、アンダースコア (_) を含めることができます。最大長は 64 文字です。

同じセッションのすべての参加者 (ホストと共同ホスト) は、同じ ChannelID を使用する必要があります。

UserId

カスタムユーザー ID です。文字列である必要があり、数字、文字、ハイフン (-)、アンダースコア (_) を含めることができます。最大長は 64 文字です。

Nonce

Nonce 文字列です。このフィールドは空のままにすることを推奨します。

Timestamp

トークンの有効期限のタイムスタンプ (秒単位) です。24 時間に設定することを推奨します。そのためには、現在の UNIX タイムスタンプに 86400 (24 × 60 × 60) を加算します。

トークン生成手順

yuque_diagram (1)

コード例:

// 1. 次のフィールドを連結します: AppID+AppKey+ChannelID+UserID+Nonce+Timestamp
// 2. 連結した文字列に sha256 関数を適用してトークンを生成します。
token = sha256(AppID+AppKey+ChannelID+UserID+Nonce+Timestamp)
// 例:
AppID = "abc",AppKey="abckey",ChannelID="abcChannel",UserID="abcUser",Nonce="",Timestamp=1699423634
token = sha256("abcabckeyabcChannelabcUser1699423634") = "3c9ee8d9f8734f0b7560ed8022a0590659113955819724fc9345ab8eedf84f31"

一般的な ARTC シナリオ

このセクションでは、トークンを使用してチャンネルへの参加をリクエストするクライアントを認証する方法を紹介し、Android と iOS の例を示します。

ARTC SDK は、チャンネルに参加するための 2 つのメソッドを提供しています:単一パラメーターメソッドと複数パラメーターメソッドです。これらは、すべての ARTC シナリオに適用できる基本的なメソッドです。

単一パラメーターメソッド (推奨)

ARTC SDK は、チャンネルに参加するための簡素化された単一パラメーターの API を提供します。このメソッドは、サーバーで生成されたパラメーターとクライアントから渡されたパラメーターの不一致による参加失敗を防ぐための糖衣構文として機能するため、使用を推奨します。

このメソッドを使用するには、TokenAppIDChannelIDNonceUserIDTimestamp パラメーターを JSON オブジェクトに結合します。次に、JSON 文字列を Base64 エンコードして、新しい認証文字列 (Base64 トークン) を生成します。

説明

トラブルシューティングのためにチケットを送信する場合は、Base64 トークンまたは joinChannel 呼び出しで渡される userName を提供してください。

yuque_diagram (3)

サーバーサイド: Base64 トークンの生成

Java

package com.example;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Calendar;
import org.json.JSONObject;

public class App {

    public static String createBase64Token(String appid, String appkey, String channelid, String userid) {
        // 有効期限のタイムスタンプを計算します (現在から 24 時間後)
        Calendar calendar = Calendar.getInstance();
        calendar.add(Calendar.HOUR_OF_DAY, 24);
        long timestamp = calendar.getTimeInMillis() / 1000;

        // 文字列を連結します
        String stringBuilder = appid + appkey + channelid + userid + timestamp;

        // SHA-256 ハッシュを計算します
        String token = sha256(stringBuilder);

        // JSON オブジェクトを作成します
        JSONObject base64tokenJson = new JSONObject();
        base64tokenJson.put("appid", appid);
        base64tokenJson.put("channelid", channelid);
        base64tokenJson.put("userid", userid);
        base64tokenJson.put("nonce", "");
        base64tokenJson.put("timestamp", timestamp);
        base64tokenJson.put("token", token);

        // JSON オブジェクトを文字列に変換し、Base64 でエンコードします
        String jsonStr = base64tokenJson.toString();
        String base64token = Base64.getEncoder().encodeToString(jsonStr.getBytes(StandardCharsets.UTF_8));
        return base64token;
    }

    private static String sha256(String input) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
            StringBuilder hexString = new StringBuilder();
            for (byte b : hash) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1)
                    hexString.append('0');
                hexString.append(hex);
            }
            return hexString.toString();
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) {
        String appid = "your_appid";
        String appkey = "your_appkey";
        String channel_id = "your_channel_id";
        String user_id = "your_user_id";

        String base64token = createBase64Token(appid, appkey, channel_id, user_id);
        System.out.println("Base64 Token: " + base64token);
    }
}

Go

package main

import (
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"time"
)

func createBase64Token(appid, appkey, channelID, userID string) (string, error) {
	// 有効期限のタイムスタンプを計算します (現在から 24 時間後)
	timestamp := time.Now().Add(24 * time.Hour).Unix()

	// 文字列を連結します
	stringBuilder := appid + appkey + channelID + userID + fmt.Sprintf("%d", timestamp)

	// SHA-256 ハッシュを計算します
	hasher := sha256.New()
	hasher.Write([]byte(stringBuilder))
	token := hasher.Sum(nil)

	// encoding/hex を使用してハッシュを 16 進文字列に変換します
	tokenHex := hex.EncodeToString(token)

	// JSON オブジェクトを作成します
	tokenJSON := map[string]interface{}{
		"appid":     appid,
		"channelid": channelID,
		"userid":    userID,
		"nonce":     "",
		"timestamp": timestamp,
		"token":     tokenHex,
	}

	// JSON オブジェクトを文字列に変換し、Base64 でエンコードします
	jsonBytes, err := json.Marshal(tokenJSON)
	if err != nil {
		return "", err
	}
	base64Token := base64.StdEncoding.EncodeToString(jsonBytes)

	return base64Token, nil
}

func main() {
	appid := "your_appid"
	appkey := "your_appkey"
	channelID := "your_channel_id"
	userID := "your_user_id"

	token, err := createBase64Token(appid, appkey, channelID, userID)
	if err != nil {
		fmt.Println("Error creating token:", err)
		return
	}
	fmt.Println("Base64 Token:", token)
}

Python

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import hashlib
import datetime
import time
import base64
import json

def create_base64_token(app_id, app_key, channel_id, user_id):
    expire = datetime.datetime.now() + datetime.timedelta(days=1)
    timestamp = int(time.mktime(expire.timetuple()))
    h = hashlib.sha256()
    h.update(str(app_id).encode('utf-8'))
    h.update(str(app_key).encode('utf-8'))
    h.update(str(channel_id).encode('utf-8'))
    h.update(str(user_id).encode('utf-8'))
    h.update(str(timestamp).encode('utf-8'))
    token = h.hexdigest()

    jsonToken = {'appid':app_id,
                 'channelid':channel_id,
                 'userid':user_id,
                 'nonce':'',
                 'timestamp':timestamp,
                 'token':token
                }
    base64Token = base64.b64encode(json.dumps(jsonToken).encode())

    return base64Token

def main():
    app_id = 'your_appid'
    app_key = 'your_appkey'
    channel_id = 'your_channel_id'
    user_id = 'your_user_id'

    base64Token = create_base64_token(app_id, app_key, channel_id, user_id)
    
    print(base64Token)

if __name__ == '__main__':
    main()

Node.js

'use strict'
const crypto = require('crypto')
function create_base64_token(appid, appkey, channelid, userid) {
    let timestamp = Math.floor(Date.now() / 1000 + 24 * 60 * 60)

    let string_builder = appid + appkey + channelid + userid + timestamp.toString()
    let token = crypto.createHash('sha256').update(string_builder).digest('hex')
    let base64tokenJson = {
        appid:appid,
        channelid:channelid,
        userid:userid,
        nonce:'',
        timestamp:timestamp,
        token:token
    }
    let base64token = Buffer.from(JSON.stringify(base64tokenJson), 'utf-8').toString('base64')
    return base64token
}

let appid = "your_appid";
let appkey = "your_appkey";
let channel_id = "your_channel_id";
let user_id = "your_user_id";

let base64token = create_base64_token(appid, appkey, channel_id, user_id)
console.log(base64token)

xRust

use chrono::{Duration, Utc};
use sha2::{Sha256, Digest};
use serde_json::json;
use base64::encode;

fn create_base64_token(appid: &str, appkey: &str, channel_id: &str, user_id: &str) -> String {
    // 有効期限のタイムスタンプを計算します (現在から 24 時間後)
    let timestamp = (Utc::now() + Duration::hours(24)).timestamp();

    // 文字列を連結します
    let string_builder = format!("{}{}{}{}{}", appid, appkey, channel_id, user_id, timestamp);

    // SHA-256 ハッシュを計算します
    let mut hasher = Sha256::new();
    hasher.update(string_builder);
    let token = hasher.finalize();
    let token_hex = format!("{:x}", token);

    // JSON オブジェクトを作成します
    let token_json = json!({
        "appid": appid,
        "channelid": channel_id,
        "userid": user_id,
        "nonce": "",
        "timestamp": timestamp,
        "token": token_hex
    });

    // JSON オブジェクトを文字列に変換し、Base64 でエンコードします
    let base64_token = encode(token_json.to_string());

    base64_token
}

fn main() {
    let appid = "your_appid";
    let appkey = "your_appkey";
    let channel_id = "your_channel_id";
    let user_id = "your_user_id";

    let token = create_base64_token(appid, appkey, channel_id, user_id);
    println!("Base64 Token: {}", token);
}

クライアントサイド: joinChannel の呼び出し

クライアントはサーバーから Base64 トークン を受け取り、joinChannel API を呼び出してチャンネルに参加します。

  • Android:

    // channelId と userId の値は Base64 トークンに含まれているため、null を渡すことができます。値を渡す場合は、トークンの生成に使用した値と一致させる必要があります。この機能は、サーバーとクライアント間のパラメーターの一貫性を検証するために使用できます。
    // base64Token は Base64 エンコードされたトークンです。
    // username は、トラブルシューティングのために渡すことができる ID です。
    mAliRtcEngine.joinChannel(base64Token, null, null, "username");
  • iOS:

    // channelId と userId の値は Base64 トークンに含まれているため、null を渡すことができます。値を渡す場合は、トークンの生成に使用した値と一致させる必要があります。この機能は、サーバーとクライアント間のパラメーターの一貫性を検証するために使用できます。
    // base64Token は Base64 エンコードされたトークンです。
    // username は、トラブルシューティングのために渡すことができる ID です。
    [self.engine joinChannel:base64Token channelId:nil userId:nil name:@"username" onResultWithUserId:nil];

複数パラメーターメソッド

ARTC SDK は、複数のパラメーターでチャンネルに参加する API も提供しています。このメソッドは、AliRtcAuthInfo データ構造を使用してトークンとユーザー情報を保持します。

重要

channelIduserId は、トークンの生成に使用されたものと一致する必要があります。

  • Android:

    // トークンとユーザー情報を渡します。
    AliRtcAuthInfo authInfo = new AliRtcAuthInfo();
    authInfo.appId = appId;
    authInfo.channelId = channelId;
    authInfo.userId = userId;
    authInfo.timestamp = timestamp;
    authInfo.nonce = nonce;
    authInfo.token = token;
    // チャンネルに参加します。
    mAliRtcEngine.joinChannel(authInfo, "");
  • iOS:

    // トークンとユーザー情報を渡します。
    let authInfo = AliRtcAuthInfo()
    authInfo.appId = appId
    authInfo.channelId = channelId
    authInfo.nonce = nonce
    authInfo.userId = userId
    authInfo.timestamp = timestamp
    authInfo.token = authToken
    // チャンネルに参加します。
    self.rtcEngine?.joinChannel(authInfo, name: nil)

共同ストリーミングシナリオ

ARTC SDK は、共同ストリーミングシナリオ専用の、より簡素化された認証方式をサポートしています。TokenAppIDChannelIDNonceUserIDTimestamp フィールドをクエリパラメーターとして、共同ストリーミング用の artc:// URL に追加できます。ARTC URL の生成に関する詳細については、「共同ストリーミング用の URL」をご参照ください。

次の図は、ワークフローを示しています。

共同ストリーミングまたはライブ対戦の URL の例

プッシュ URL:

artc://live.aliyun.com/push/633?timestamp=1685094092&token=fe4e674ade****6686&userId=718&sdkAppId=xxx

プル URL:

artc://live.aliyun.com/play/633?timestamp=1685094092&token=fe4e674ade****6686&userId=718&sdkAppId=xxx
説明

live.aliyun.com は、共同ストリーミング URL の固定プレフィックスであり、解決可能なドメイン名ではありません。ping、traceroute、telnet などのドメイン関連の操作には使用できません。

トークンの有効期限の処理

トークンが作成されると、Timestamp フィールドでその有効期限が指定されます。

ユーザーがトークンでチャンネルに参加した後:

  • トークンの有効期限が切れる 30 秒前に、SDK は onAuthInfoWillExpire コールバックをトリガーします。refreshAuthInfo メソッドを呼び出して認証情報を更新します。

  • トークンの有効期限が切れると、SDK は onAuthInfoExpired コールバックをトリガーします。チャンネルに留まるには、ユーザーは再度チャンネルに参加する必要があります。