All Products
Search
Document Center

ApsaraVideo Live:Sample code for URL signing

Last Updated:Sep 04, 2024

This topic provides sample code on how to construct and use a custom signed URL and how to update the URL signing settings.

Generate a signed URL

Construct a custom signed URL

In actual business scenarios, you may need to dynamically generate ingest and streaming URLs. In this case, you can obtain the URL signing settings and construct the URLs by using the concatenation rules. This section uses the server SDK for Java as an example to describe how to dynamically construct ingest and streaming URLs.

Note

For information about the structure of a signed URL, see Construct a signed URL.

Because a signed URL must be encrypted based on the authentication key and the validity period, you must obtain the URL signing settings before you can dynamically construct ingest and streaming URLs.

To obtain the URL signing settings, call the DescribeLiveDomainConfigs operation to query the domain name configurations. Sample code:

// Replace the content in <> with actual values.
DefaultProfile profile = DefaultProfile.getProfile("<regionId>", "<ALIBABA_CLOUD_ACCESS_KEY_ID>", "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>");
IAcsClient client = new DefaultAcsClient(profile);
DescribeLiveDomainConfigsRequest describeLiveDomainConfigsRequest=new DescribeLiveDomainConfigsRequest();
describeLiveDomainConfigsRequest.setDomainName("<DomainName>");
describeLiveDomainConfigsRequest.setFunctionNames("aliauth");

DescribeLiveDomainConfigsResponse describeLiveStreamSnapshotInfoResponse = null;
try {
     describeLiveStreamSnapshotInfoResponse = client.getAcsResponse(describeLiveDomainConfigsRequest);
 } catch (ClientException e) {
     e.printStackTrace();
}
The authentication key.
String key="";
// The valid period. Unit: seconds.
long expSeconds=0l;

for(DescribeLiveDomainConfigsResponse.DomainConfig.FunctionArg f:describeLiveStreamSnapshotInfoResponse.getDomainConfigs().get(0).getFunctionArgs()){
     if("auth_key1".equals(f.getArgName())){
            key=f.getArgValue();
       }
     if("ali_auth_delta".equals(f.getArgName())){
            expSeconds=Long.valueOf(f.getArgValue());
     }
 }

 System.out.println(key);
 System.out.println(expSeconds);

After you obtain the authentication key and validity period, you can construct and encrypt the URLs. For the relevant sample code, see the Sample code in Java section under "Use a signed URL for encryption" in this topic.

Note
  • When you generate an ingest URL, you must use the authentication key and validity period of the ingest domain.

  • When you generate a streaming URL, you must use the authentication key and validity period of the streaming domain.

Update the URL signing settings

In actual business scenarios, you may need to update the authentication key on a regular basis, which is also a practice that we recommend. In this case, you can call the BatchSetLiveDomainConfigs operation to update the URL signing settings for the domain names.

This section uses the server SDK for Java as an example to describe how to update the URL signing settings. Sample code:

// Replace the content in <> with actual values.
DefaultProfile profile = DefaultProfile.getProfile("<regionId>", "<ALIBABA_CLOUD_ACCESS_KEY_ID>", "<ALIBABA_CLOUD_ACCESS_KEY_SECRET>");
IAcsClient client = new DefaultAcsClient(profile);
BatchSetLiveDomainConfigsRequest batchSetLiveDomainConfigsRequest =new BatchSetLiveDomainConfigsRequest();
batchSetLiveDomainConfigsRequest.setDomainNames("<DomainName>");
batchSetLiveDomainConfigsRequest.setFunctions("[{\"functionArgs\":[" +
        "{\"argName\":\"auth_type\",\"argValue\":\"type_a\"}," +
        "{\"argName\":\"auth_key1\",\"argValue\":\"<KEY_MAIN****>\"}," +
        "{\"argName\":\"auth_key2\",\"argValue\":\"<KEY_BAK****>\"}," +
        "{\"argName\":\"ali_auth_delta\",\"argValue\":<3600>}]," +
        "\"functionName\":\"aliauth\"}]");
try {
    BatchSetLiveDomainConfigsResponse response = client.getAcsResponse(batchSetLiveDomainConfigsRequest);
    System.out.println(new Gson().toJson(response));
    //todo something
} catch (ServerException e) {
    e.printStackTrace();
} catch (ClientException e) {
    e.printStackTrace();
}
Note
  • The preceding sample code updates the URL signing settings for the domain name <DomainName>. The authentication type is type_a, which indicates that URL signing is enabled. The value of auth_key1, which indicates the primary key, is KEY_MAIN****. The value of auth_key2, which indicates the secondary key, is KEY_BAK****. The value of ali_auth_delta, which indicates the validity period of a signed URL, is 3600 seconds.

  • The primary key and secondary key have the same functionality. The secondary key is used for smooth key replacement. If you change the primary key, all generated streaming URLs that use the original primary key immediately become invalid. If you switch from the primary key to the secondary key, the generated streaming URLs that use the original primary key remain valid. The secondary key works as a primary key.

Use a signed URL for encryption

Sample code in Java

import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AuthDemo {
    private static String md5Sum(String src) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        md5.update(StandardCharsets.UTF_8.encode(src));
        return String.format("%032x", new BigInteger(1, md5.digest()));
    }

private static String aAuth(String uri, String key, long exp) {
    String pattern = "^(rtmp://)?([^/?]+)(/[^?]*)?(\\\\?.*)?$";
    Pattern r = Pattern.compile(pattern);
    Matcher m = r.matcher(uri);
    String scheme = "", host = "", path = "", args = "";
    if (m.find()) {
        scheme = m.group(1) == null ?  "rtmp://" : m.group(1);
        host = m.group(2) == null ?  "" : m.group(2);
        path = m.group(3) == null ?  "/" : m.group(3);
        args = m.group(4) == null ?  "" : m.group(4);
    } else {
        System.out.println("NO MATCH");
    }

    String rand = "0";  // "0" by default, other value is ok
    String uid = "0";   // "0" by default, other value is ok
    String sString = String.format("%s-%s-%s-%s-%s", path, exp, rand, uid, key);
    String hashValue = md5Sum(sString);
    String authKey = String.format("%s-%s-%s-%s", exp, rand, uid, hashValue);
    if (args.isEmpty()) {
        return String.format("%s%s%s%s?auth_key=%s", scheme, host, path, args, authKey);
    } else {
        return String.format("%s%s%s%s&auth_key=%s", scheme, host, path, args, authKey);
    }
}

public static void main(String[] args) {
    String uri = "rtmp://example.aliyundoc.com/live/test****";  // original uri
    String key = "<input private key>";                       // private key of authorization
    long exp = System.currentTimeMillis() / 1000 + 1 * 3600;  // expiration time: 1 hour after current time
    String authUri = aAuth(uri, key, exp);                    
    System.out.printf("URL : %s\nAuth: %s", uri, authUri);
}
}

Sample code in Python

import re
import time
import hashlib
import datetime
def md5sum(src):
    m = hashlib.md5()
    m.update(src)
    return m.hexdigest()
def a_auth(uri, key, exp):
    p = re.compile("^(rtmp://)?([^/?]+)(/[^?]*)?(\\?.*)?$")
    if not p:
        return None
    m = p.match(uri)
    scheme, host, path, args = m.groups()
    if not scheme: scheme = "rtmp://"
    if not path: path = "/"
    if not args: args = ""
    rand = "0"      # "0" by default, other value is ok
    uid = "0"       # "0" by default, other value is ok
    sstring = "%s-%s-%s-%s-%s" %(path, exp, rand, uid, key)
    hashvalue = md5sum(sstring.encode('utf-8'))
    auth_key = "%s-%s-%s-%s" %(exp, rand, uid, hashvalue)
    if args:
        return "%s%s%s%s&auth_key=%s" %(scheme, host, path, args, auth_key)
    else:
        return "%s%s%s%s?auth_key=%s" %(scheme, host, path, args, auth_key)
def main():
    uri = "rtmp://example.aliyundoc.com/test/test?vhost=demo.aliyundoc.liucom"            # original uri
    key = "<input private key>"                         # private key of     authorization
    exp = int(time.time()) + 1 * 3600                   # expiration     time: 1 hour after current itme
    authuri = a_auth(uri, key, exp)                     
    print("URL : %s\nAUTH: %s" %(uri, authuri))
if __name__ == "__main__":
    main()

Sample code in Go

package main
import (
    "crypto/md5"
    "encoding/hex"
    "fmt"
    "regexp"
    "time"
)

func md5sum(src string) string {
    h := md5.New()
    h.Write([]byte(src))
    return hex.EncodeToString(h.Sum(nil))
}

func a_auth(uri, key string, exp int64) string {
    p, err := regexp.Compile("^(rtmp://)?([^/?]+)(/[^?]*)?(\\?.*)?$")
    if err != nil {
        fmt.Println(err)
        return ""
    }
    m := p.FindStringSubmatch(uri)
    var scheme, host, path, args string
    if len(m) == 5 {
        scheme, host, path, args = m[1], m[2], m[3], m[4]
    } else {
        scheme, host, path, args = "rtmp://", "", "/", ""
    }
    rand := "0" // "0" by default, other value is ok
    uid := "0"  // "0" by default, other value is ok
    sstring := fmt.Sprintf("%s-%d-%s-%s-%s", path, exp, rand, uid, key)
    hashvalue := md5sum(sstring)
    auth_key := fmt.Sprintf("%d-%s-%s-%s", exp, rand, uid, hashvalue)
    if len(args) != 0 {
        return fmt.Sprintf("%s%s%s%s&auth_key=%s", scheme, host, path, args, auth_key)
    } else {
        return fmt.Sprintf("%s%s%s%s?auth_key=%s", scheme, host, path, args, auth_key)
    }
}

func main() {
    uri := "rtmp://example.aliyundoc.com/live/test****" // original uri
    key := "<input private key>"                                           // private key of authorization
    exp := time.Now().Unix() + 3600                                        // expiration time: 1 hour after current itme
    authuri := a_auth(uri, key, exp)                                       
    fmt.Printf("URL : %s\nAUTH: %s", uri, authuri)
}

Sample code in PHP

<?php
function a_auth($uri, $key, $exp) {
    preg_match("/^(rtmp:\/\/)?([^\/?]+)?(\/[^?]*)?(\\?.*)?$/", $uri, $matches);
    $scheme = $matches[1];
    $host = $matches[2];
    $path = $matches[3];
    $args = $matches[4];
    if  (empty($args)) {
        $args ="";
    }
    if  (empty($scheme)) {
        $scheme ="rtmp://";
    }
    if  (empty($path)) {
        $path ="/";
    }
    $rand = "0";
    // "0" by default, other value is ok
    $uid = "0";
    // "0" by default, other value is ok
    $sstring = sprintf("%s-%u-%s-%s-%s", $path, $exp, $rand, $uid, $key);
    $hashvalue = md5($sstring);
    $auth_key = sprintf("%u-%s-%s-%s", $exp, $rand, $uid, $hashvalue);
    if ($args) {
        return sprintf("%s%s%s%s&auth_key=%s", $scheme, $host, $path, $args, $auth_key);
    } else {
        return sprintf("%s%s%s%s?auth_key=%s", $scheme, $host, $path, $args, $auth_key);
    }
}
$uri = "rtmp://example.aliyundoc.com/live/test****";
$key = "<input private key>";
$exp = time() + 3600;
$authuri = a_auth($uri, $key, $exp);
echo "URL :" . $uri;
echo PHP_EOL;
echo "AUTH:" . $authuri;
?>

Sample code in C#

using System;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Text;
public class Test
{
    public static void Main()
    {
        string uri= "rtmp://example.aliyundoc.com/live/test****";  // original uri
        string key= "<input private key>";                           // private key of authorization
           DateTime dateStart = new DateTime(1970, 1, 1, 8, 0, 0);
         string exp  = Convert.ToInt64((DateTime.Now - dateStart).TotalSeconds+3600).ToString(); // expiration time: 1 hour after current time
        string authUri = aAuth(uri, key, exp);
        Console.WriteLine (String.Format("URL :{0}",uri));
        Console.WriteLine (String.Format("AUTH :{0}",authUri));
    }
    public static string aAuth(string uri, string key, string exp)
    {
        Regex regex = new Regex("^(rtmp://)?([^/?]+)(/[^?]*)?(\\\\?.*)?$");
        Match m = regex.Match(uri);
        string scheme = "rtmp://", host = "", path = "/", args = "";
        if (m.Success)
        {
            scheme=m.Groups[1].Value;
            host=m.Groups[2].Value;
            path=m.Groups[3].Value;
            args=m.Groups[4].Value;
        }else{
            Console.WriteLine ("NO MATCH");
        }
        string rand = "0";  // "0" by default, other value is ok
        string uid = "0";   // "0" by default, other value is ok
        string u = String.Format("{0}-{1}-{2}-{3}-{4}",  path, exp, rand, uid, key);
        string hashValue  = Md5(u);
        string authKey = String.Format("{0}-{1}-{2}-{3}", exp, rand, uid, hashValue);
        if (args=="")
        {
            return String.Format("{0}{1}{2}{3}?auth_key={4}", scheme, host, path, args, authKey);
        } else
        {
            return String.Format("{0}{1}{2}{3}&auth_key={4}", scheme, host, path, args, authKey);
        }
    }
    public static string Md5(string value)
    {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
        byte[] bytes = Encoding.ASCII.GetBytes(value);
        byte[] encoded = md5.ComputeHash(bytes);
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<encoded.Length; ++i)
        {
            sb.Append(encoded[i].ToString("x2"));
        }
        return sb.ToString();
   }
}

References

For more information about access control, see the Access control topic in Developer Guide.

For more information about how to use the server SDK for Java, see Use the server SDK for Java.