Tokens generieren

In dieser Anleitung wird erklärt, wie Sie ein Token generieren und welche Felder für Tokens erforderlich und optional sind.

Um ein Token zu erstellen, erstellen Sie eine zu signierende Zeichenfolge, die wir als signierte Wert in diesem Leitfaden. Der vorzeichenbehaftete Wert enthält Parameter, die den Inhalte, die Sie schützen, die Ablaufzeit des signierten Werts usw. weiter.

Sie verwenden den signierten Wert beim Erstellen eines Tokenstrings. Zum Erstellen eines Token-Strings erstellen Sie die Parameter für das Token, z. B. einen Hash-basierten Message Authentication Code (HMAC) mit Symmetrieschlüssel des signierten Werts.

Media CDN verwendet das Token für die endgültige Erstellung, um Ihre Inhalte.

Token erstellen

  1. Erstellen Sie einen signierten Wert, indem Sie einen String verketten, der den Parameter Erforderliche Token-Felder und gewünschte optionale Tokens enthalten. Trennen Sie die einzelnen Felder und Parameter durch ein Tildezeichen ~.

  2. Signieren Sie den signierten Wert entweder mit einer Ed25519-Signatur oder einem symmetrischen HMAC-Schlüssel.

  3. Erstellen Sie das Token, indem Sie einen String mit den erforderlichen und optionalen Tokenfeldern zusammenführen. Trennen Sie die einzelnen Felder und Parameter durch ein Tildezeichen ~.

    Beim Erstellen des Tokens sind die Werte für jeden der Parameter die ist gleich zwischen dem signierten Wert und dem Tokenstring, wobei Folgendes verwendet wird: Ausnahmen:

    • FullPath
    • Headers

Das folgende Codebeispiel zeigt, wie ein Token programmatisch erstellt wird:

Python

Richten Sie Standardanmeldedaten für Anwendungen ein, um sich bei Media CDN zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

import base64
import datetime
import hashlib
import hmac

import cryptography.hazmat.primitives.asymmetric.ed25519 as ed25519


def base64_encoder(value: bytes) -> str:
    """
    Returns a base64-encoded string compatible with Media CDN.

    Media CDN uses URL-safe base64 encoding and strips off the padding at the
    end.
    """
    encoded_bytes = base64.urlsafe_b64encode(value)
    encoded_str = encoded_bytes.decode("utf-8")
    return encoded_str.rstrip("=")


def sign_token(
    base64_key: bytes,
    signature_algorithm: str,
    start_time: datetime.datetime = None,
    expiration_time: datetime.datetime = None,
    url_prefix: str = None,
    full_path: str = None,
    path_globs: str = None,
    session_id: str = None,
    data: str = None,
    headers: str = None,
    ip_ranges: str = None,
) -> str:
    """Gets the Signed URL Suffix string for the Media CDN' Short token URL requests.
    One of (`url_prefix`, `full_path`, `path_globs`) must be included in each input.
    Args:
        base64_key: Secret key as a base64 encoded string.
        signature_algorithm: Algorithm can be either `SHA1` or `SHA256` or `Ed25519`.
        start_time: Start time as a UTC datetime object.
        expiration_time: Expiration time as a UTC datetime object. If None, an expiration time 1 hour from now will be used.
        url_prefix: the URL prefix to sign, including protocol.
                    For example: http://example.com/path/ for URLs under /path or http://example.com/path?param=1
        full_path:  A full path to sign, starting with the first '/'.
                    For example: /path/to/content.mp4
        path_globs: a set of ','- or '!'-delimited path glob strings.
                    For example: /tv/*!/film/* to sign paths starting with /tv/ or /film/ in any URL.
        session_id: a unique identifier for the session
        data: data payload to include in the token
        headers: header name and value to include in the signed token in name=value format.  May be specified more than once.
                    For example: [{'name': 'foo', 'value': 'bar'}, {'name': 'baz', 'value': 'qux'}]
        ip_ranges: A list of comma separated ip ranges. Both IPv4 and IPv6 ranges are acceptable.
                    For example: "203.0.113.0/24,2001:db8:4a7f:a732/64"

    Returns:
        The Signed URL appended with the query parameters based on the
        specified URL prefix and configuration.
    """

    decoded_key = base64.urlsafe_b64decode(base64_key)
    algo = signature_algorithm.lower()

    # For most fields, the value we put in the token and the value we must sign
    # are the same.  The FullPath and Headers use a different string for the
    # value to be signed compared to the token.  To illustrate this difference,
    # we'll keep the token and the value to be signed separate.
    tokens = []
    to_sign = []

    # check for `full_path` or `path_globs` or `url_prefix`
    if full_path:
        tokens.append("FullPath")
        to_sign.append(f"FullPath={full_path}")
    elif path_globs:
        path_globs = path_globs.strip()
        field = f"PathGlobs={path_globs}"
        tokens.append(field)
        to_sign.append(field)
    elif url_prefix:
        field = "URLPrefix=" + base64_encoder(url_prefix.encode("utf-8"))
        tokens.append(field)
        to_sign.append(field)
    else:
        raise ValueError(
            "User Input Missing: One of `url_prefix`, `full_path` or `path_globs` must be specified"
        )

    # check & parse optional params
    if start_time:
        epoch_duration = start_time.astimezone(
            tz=datetime.timezone.utc
        ) - datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc)
        field = f"Starts={int(epoch_duration.total_seconds())}"
        tokens.append(field)
        to_sign.append(field)

    if not expiration_time:
        expiration_time = datetime.datetime.now() + datetime.timedelta(hours=1)
        epoch_duration = expiration_time.astimezone(
            tz=datetime.timezone.utc
        ) - datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc)
    else:
        epoch_duration = expiration_time.astimezone(
            tz=datetime.timezone.utc
        ) - datetime.datetime.fromtimestamp(0, tz=datetime.timezone.utc)
    field = f"Expires={int(epoch_duration.total_seconds())}"
    tokens.append(field)
    to_sign.append(field)

    if session_id:
        field = f"SessionID={session_id}"
        tokens.append(field)
        to_sign.append(field)

    if data:
        field = f"Data={data}"
        tokens.append(field)
        to_sign.append(field)

    if headers:
        header_names = []
        header_pairs = []
        for each in headers:
            header_names.append(each["name"])
            header_pairs.append("%s=%s" % (each["name"], each["value"]))
        tokens.append(f"Headers={','.join(header_names)}")
        to_sign.append(f"Headers={','.join(header_pairs)}")

    if ip_ranges:
        field = f"IPRanges={base64_encoder(ip_ranges.encode('ascii'))}"
        tokens.append(field)
        to_sign.append(field)

    # generating token
    to_sign = "~".join(to_sign)
    to_sign_bytes = to_sign.encode("utf-8")
    if algo == "ed25519":
        digest = ed25519.Ed25519PrivateKey.from_private_bytes(decoded_key).sign(
            to_sign_bytes
        )
        tokens.append("Signature=" + base64_encoder(digest))
    elif algo == "sha256":
        signature = hmac.new(
            decoded_key, to_sign_bytes, digestmod=hashlib.sha256
        ).hexdigest()
        tokens.append("hmac=" + signature)
    elif algo == "sha1":
        signature = hmac.new(
            decoded_key, to_sign_bytes, digestmod=hashlib.sha1
        ).hexdigest()
        tokens.append("hmac=" + signature)
    else:
        raise ValueError(
            "Input Missing Error: `signature_algorithm` can only be one of `sha1`, `sha256` or `ed25519`"
        )
    return "~".join(tokens)

Java

Richten Sie Standardanmeldedaten für Anwendungen ein, um sich bei Media CDN zu authentifizieren. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.


import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Optional;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.crypto.params.Ed25519PrivateKeyParameters;
import org.bouncycastle.crypto.signers.Ed25519Signer;
import org.bouncycastle.util.encoders.Hex;

public class DualToken {

  public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
    // TODO(developer): Replace these variables before running the sample.
    // Secret key as a base64 encoded string.
    byte[] base64Key = new byte[]{};
    // Algorithm can be one of these: SHA1, SHA256, or Ed25519.
    String signatureAlgorithm = "ed25519";
    // (Optional) Start time as a UTC datetime object.
    DateTimeFormatter formatter = DateTimeFormatter.ISO_INSTANT;
    Optional<Instant> startTime = Optional.empty();
    // Expiration time as a UTC datetime object.
    // If None, an expiration time that's an hour after the current time is used.
    Instant expiresTime = Instant.from(formatter.parse("2022-09-13T12:00:00Z"));

    // ONE OF (`urlPrefix`, `fullPath`, `pathGlobs`) must be included in each input.
    // The URL prefix and protocol to sign.
    // For example: http://example.com/path/ for URLs under /path or http://example.com/path?param=1
    Optional<String> urlPrefix = Optional.empty();
    // A full path to sign, starting with the first '/'.
    // For example: /path/to/content.mp4
    Optional<String> fullPath = Optional.of("http://10.20.30.40/");
    // A set of path glob strings delimited by ',' or '!'.
    // For example: /tv/*!/film/* to sign paths starting with /tv/ or /film/ in any URL.
    Optional<String> pathGlobs = Optional.empty();

    // (Optional) A unique identifier for the session.
    Optional<String> sessionId = Optional.empty();
    // (Optional) Data payload to include in the token.
    Optional<String> data = Optional.empty();
    // (Optional) Header name and value to include in the signed token in name=value format.
    // May be specified more than once.
    // For example: [{'name': 'foo', 'value': 'bar'}, {'name': 'baz', 'value': 'qux'}]
    Optional<List<Header>> headers = Optional.empty();
    // (Optional) A list of comma-separated IP ranges. Both IPv4 and IPv6 ranges are acceptable.
    // For example: "203.0.113.0/24,2001:db8:4a7f:a732/64"
    Optional<String> ipRanges = Optional.empty();

    DualToken.signToken(
        base64Key,
        signatureAlgorithm,
        startTime,
        expiresTime,
        urlPrefix,
        fullPath,
        pathGlobs,
        sessionId,
        data,
        headers,
        ipRanges);
  }

  // Gets the signed URL suffix string for the Media CDN short token URL requests.
  // Result:
  //     The signed URL appended with the query parameters based on the
  // specified URL prefix and configuration.
  public static void signToken(
      byte[] base64Key, String signatureAlgorithm, Optional<Instant> startTime,
      Instant expirationTime, Optional<String> urlPrefix, Optional<String> fullPath,
      Optional<String> pathGlobs, Optional<String> sessionId, Optional<String> data,
      Optional<List<Header>> headers, Optional<String> ipRanges)
      throws NoSuchAlgorithmException, InvalidKeyException {

    String field = "";
    byte[] decodedKey = Base64.getUrlDecoder().decode(base64Key);

    // For most fields, the value in the token and the value to sign
    // are the same. Compared to the token, the FullPath and Headers
    // use a different string for the value to sign. To illustrate this difference,
    // we'll keep the token and the value to be signed separate.
    List<String> tokens = new ArrayList<>();
    List<String> toSign = new ArrayList<>();

    // Check for `fullPath` or `pathGlobs` or `urlPrefix`.
    if (fullPath.isPresent()) {
      tokens.add("FullPath");
      toSign.add(String.format("FullPath=%s", fullPath.get()));
    } else if (pathGlobs.isPresent()) {
      field = String.format("PathGlobs=%s", pathGlobs.get().trim());
      tokens.add(field);
      toSign.add(field);
    } else if (urlPrefix.isPresent()) {
      field = String.format("URLPrefix=%s",
          base64Encoder(urlPrefix.get().getBytes(StandardCharsets.UTF_8)));
      tokens.add(field);
      toSign.add(field);
    } else {
      throw new IllegalArgumentException(
          "User Input Missing: One of `urlPrefix`, `fullPath` or `pathGlobs` must be specified");
    }

    // Check & parse optional params.
    long epochDuration;
    if (startTime.isPresent()) {
      epochDuration = ChronoUnit.SECONDS.between(Instant.EPOCH, startTime.get());
      field = String.format("Starts=%s", epochDuration);
      tokens.add(field);
      toSign.add(field);
    }

    if (expirationTime == null) {
      expirationTime = Instant.now().plus(1, ChronoUnit.HOURS);
    }
    epochDuration = ChronoUnit.SECONDS.between(Instant.EPOCH, expirationTime);
    field = String.format("Expires=%s", epochDuration);
    tokens.add(field);
    toSign.add(field);

    if (sessionId.isPresent()) {
      field = String.format("SessionID=%s", sessionId.get());
      tokens.add(field);
      toSign.add(field);
    }

    if (data.isPresent()) {
      field = String.format("Data=%s", data.get());
      tokens.add(field);
      toSign.add(field);
    }

    if (headers.isPresent()) {
      List<String> headerNames = new ArrayList<>();
      List<String> headerPairs = new ArrayList<>();

      for (Header entry : headers.get()) {
        headerNames.add(entry.getName());
        headerPairs.add(String.format("%s=%s", entry.getName(), entry.getValue()));
      }
      tokens.add(String.format("Headers=%s", String.join(",", headerNames)));
      toSign.add(String.format("Headers=%s", String.join(",", headerPairs)));
    }

    if (ipRanges.isPresent()) {
      field = String.format("IPRanges=%s",
          base64Encoder(ipRanges.get().getBytes(StandardCharsets.US_ASCII)));
      tokens.add(field);
      toSign.add(field);
    }

    // Generate token.
    String toSignJoined = String.join("~", toSign);
    byte[] toSignBytes = toSignJoined.getBytes(StandardCharsets.UTF_8);
    String algorithm = signatureAlgorithm.toLowerCase();

    if (algorithm.equalsIgnoreCase("ed25519")) {
      Ed25519PrivateKeyParameters privateKey = new Ed25519PrivateKeyParameters(decodedKey, 0);
      Ed25519Signer signer = new Ed25519Signer();
      signer.init(true, privateKey);
      signer.update(toSignBytes, 0, toSignBytes.length);
      byte[] signature = signer.generateSignature();
      tokens.add(String.format("Signature=%s", base64Encoder(signature)));
    } else if (algorithm.equalsIgnoreCase("sha256")) {
      String sha256 = "HmacSHA256";
      Mac mac = Mac.getInstance(sha256);
      SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, sha256);
      mac.init(secretKeySpec);
      byte[] signature = mac.doFinal(toSignBytes);
      tokens.add(String.format("hmac=%s", Hex.toHexString(signature)));
    } else if (algorithm.equalsIgnoreCase("sha1")) {
      String sha1 = "HmacSHA1";
      Mac mac = Mac.getInstance(sha1);
      SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, sha1);
      mac.init(secretKeySpec);
      byte[] signature = mac.doFinal(toSignBytes);
      tokens.add(String.format("hmac=%s", Hex.toHexString(signature)));
    } else {
      throw new Error(
          "Input Missing Error: `signatureAlgorithm` can only be one of `sha1`, `sha256` or "
              + "`ed25519`");
    }
    // The signed URL appended with the query parameters based on the
    // specified URL prefix and configuration.
    System.out.println(String.join("~", tokens));
  }

  // Returns a base64-encoded string compatible with Media CDN.
  // Media CDN uses URL-safe base64 encoding and strips off the padding at the
  // end.
  public static String base64Encoder(byte[] value) {
    byte[] encodedBytes = Base64.getUrlEncoder().withoutPadding().encode(value);
    return new String(encodedBytes, StandardCharsets.UTF_8);
  }

  public static class Header {

    private String name;
    private String value;

    public Header(String name, String value) {
      this.name = name;
      this.value = value;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }

    public String getValue() {
      return value;
    }

    public void setValue(String value) {
      this.value = value;
    }

    @Override
    public String toString() {
      return "Header{"
          + "name='" + name + '\''
          + ", value='" + value + '\''
          + '}';
    }
  }

}

In den folgenden Abschnitten werden die von Tokens verwendeten Felder beschrieben.

Erforderliche Tokenfelder

Die folgenden Felder sind für jedes Token erforderlich:

  • Expires
  • Einer der folgenden Typen:
    • PathGlobs
    • URLPrefix
    • FullPath
  • Eine der folgenden Möglichkeiten:
    • Signature
    • hmac

Sofern nicht anders angegeben, wird bei Parameternamen und ihren Werten die Groß-/Kleinschreibung beachtet.

In der folgenden Tabelle werden die einzelnen Parameter erläutert:

Feldname / Aliasse Tokenparameter Signierter Wert

Expires

exp

Ganzzahlige Sekunden, die seit der Unix-Epoche vergangen sind (1970-01-01T00:00:00Z) Expires=EXPIRATION_TIME, danach ist das Token nicht mehr gültig.

PathGlobs

paths, acl

Eine Liste mit bis zu fünf Pfadsegmenten, auf die Zugriff gewährt werden soll. Die Segmente können entweder durch Kommas (,) oder Ausrufezeichen (!) abgegrenzt werden, aber nicht durch beides.

PathGlobs unterstützt Platzhalterzeichen in Pfaden mithilfe von Sternchen (*) und Fragezeichen (?) Eine einzelne Sternchen (*) für eine beliebige Anzahl von Pfadsegmenten, im Gegensatz zur Musterabgleichssyntax für pathMatchTemplate.

Pfadparameter, die durch Semikolons (;) gekennzeichnet sind, sind nicht zulässig, da sie beim Abgleich für Unklarheiten sorgen.

Achten Sie daher darauf, dass Ihre URL keine der folgenden Sonderzeichen enthält: ,!*?;

PathGlobs=PATHS
URLPrefix

Eine websichere Base64-codierte URL, die das Protokoll http:// oder https:// bis zu einem Punkt Ihrer Wahl enthält.

Einige gültige URLPrefix-Werte für „https://beispiel.de/foo/bar.ts“ sind „https://beispiel.de“, „https://beispiel.de/foo“ und „https://beispiel.de/foo/bar“.

URLPrefix=BASE_64_URL_PREFIX
FullPath – Wenn Sie FullPath in einem Token angeben, dürfen Sie den Pfad, den Sie im signierten Wert angegeben haben, nicht duplizieren. Fügen Sie in einem Token den Feldnamen ohne = ein. FullPath=FULL_PATH_TO_OBJECT
Signature Eine websichere, mit Base64 codierte Version der Signatur. Nicht zutreffend
hmac Eine websichere Base64-codierte Version des HMAC-Werts. Nicht zutreffend

Platzhaltersyntax PathGlobs

In der folgenden Tabelle wird die Syntax des Platzhalters PathGlobs erläutert.

Operator Stimmt überein mit Beispiele
* (Sternchen) Stimmt mit null oder mehr Zeichen im Pfad der URL überein, einschließlich Schrägstrich-Zeichen (/).
  • /videos/* entspricht jedem Pfad, der mit /videos/ beginnt.
  • /videos/s*/4k/* entspricht /videos/s/4k/ und /videos/s01/4k/main.m3u8.
  • /manifests/*/4k/* Übereinstimmungen /manifests/s01/4k/main.m3u8 und /manifests/s01/e01/4k/main.m3u8 Sie stimmt nicht mit /manifests/4k/main.m3u8 überein.
? (Fragezeichen) Entspricht einem einzelnen Zeichen im Pfad der URL, ohne Schrägstriche (/). /videos/s?main.m3u8 Übereinstimmungen /videos/s1main.m3u8. Er entspricht weder /videos/s01main.m3u8 noch /videos/s/main.m3u8.

Globs für URL-Pfade müssen entweder mit einem Sternchen (*) oder einem Schrägstrich (/) beginnen.

Da * und /* mit allen URL-Pfaden übereinstimmen, raten wir davon ab, Verwenden Sie eines der beiden in Ihren signierten Tokens. Für maximalen Schutz sollten Ihre Globs mit den Inhalten übereinstimmen, für die Sie Zugriff gewähren möchten.

Optionale Tokenfelder

Sofern nicht anders angegeben, wird bei Parameternamen und ihren Werten die Groß-/Kleinschreibung beachtet.

In der folgenden Tabelle werden Parameternamen, Aliasse und Details zu optionalen Parametern erläutert:

Feldname / Aliasse Parameter Signierter Wert

Starts

st

Ganzzahlsekunden seit der Unix-Epoche (1970-01-01T00:00:00Z) Starts=START_TIME
IPRanges

Eine Liste von bis zu fünf IPv4- und IPv6-Adressen im CIDR-Format, für die diese URL im websicheren Base64-Format gültig ist. Beispiel: zum Angeben der IP-Bereiche „192.6.13.13/32,193.5.64.135/32“, geben Sie IPRanges=MTkyLjYuMTMuMTMvMzIsMTkzLjUuNjQuMTM1LzMy

Die Aufnahme von IPRanges in die Tokens ist möglicherweise nicht sinnvoll, wenn Kunden von WAN-Migrationen bedroht sind oder wenn der Netzwerkpfad zu Ihrem Anwendungs-Frontend ein anderer ist als der Bereitstellungspfad. Media CDN lehnt Clients mit einem HTTP 403-Code ab, wenn sie eine Verbindung über eine IP-Adresse herstellen, die nicht Teil der signierten Anfrage ist.

In den folgenden Fällen kann es passieren, dass Media CDN Clients mit einem HTTP 403-Code ablehnt:

  • Dual-Stack-Umgebungen (IPv4, IPv6)
  • Verbindungsmigration (WLAN zu Mobilfunk und Mobilfunk zu WLAN)
  • Mobilfunknetze, die Carrier Gateway NAT (CGNAT oder CGN) verwenden
  • Multi-Path-TCP (MPTCP)

All diese Faktoren können dazu beitragen, dass ein bestimmter Client während einer Videowiedergabesitzung eine nicht-deterministische IP-Adresse hat. Wenn der Parameter Client-IP-Adresse ändert sich, nachdem Sie Zugriff gewährt haben, und Client versucht, ein Videosegment in die Wiedergabe herunterzuladen. erhält er eine HTTP 403 von Media CDN.

IPRanges=BASE_64_IP_RANGES

SessionID

id

Ein beliebiger String, der für die Analyse von Protokollen oder die Wiedergabe-Analyse nützlich ist.

Verwenden Sie %-codierte oder websichere Base64-codierte Strings, um ein ungültiges Token zu vermeiden. Die folgenden Zeichen dürfen nicht für SessionID, da sie dazu führen, dass das Token ungültig wird: „~“, „&“ oder „ “ (Leerzeichen).

SessionID=SESSION_ID_VALUE

Data

data, payload

Ein beliebiger String, nützlich für die Loganalyse.

Verwenden Sie %-codiert oder websicher, um das Erstellen eines ungültigen Tokens zu vermeiden base64-codierte Strings. Die folgenden Zeichen dürfen nicht für Data, da sie dazu führen, dass das Token ungültig wird: „~“, „&“ oder „ “ (Leerzeichen).

data=DATA_VALUE
Headers Eine durch Kommas getrennte Liste von Header-Feldnamen. Headernamen sind Groß- und Kleinschreibung für Lookups in der Anfrage nicht berücksichtigt wird. Headernamen in der signierten Datei wird zwischen Groß- und Kleinschreibung unterschieden. Wenn ein Header fehlt, ist der Wert ein leerer String. Wenn es mehrere Kopien eines Headers gibt, werden sie durch Kommas getrennt. Headers=HEADER_1_NAME=HEADER_1_EXPECTED_VALUE, HEADER_2_NAME=HEADER_2_EXPECTED_VALUE

Beispiele

Die folgenden Abschnitte enthalten Beispiele zum Generieren von Tokens.

Beispiel mit FullPath

Sehen Sie sich das folgende Beispiel mit dem Feld FullPath an:

  • Angeforderter Artikel: http://example.com/tv/my-show/s01/e01/playlist.m3u8
  • Ablaufzeit: 160000000

Der signierte Wert ist:

Expires=160000000~FullPath=/tv/my-show/s01/e01/playlist.m3u8

Signieren Sie den signierten Wert entweder mit einer Ed25519-Signatur oder mit einem symmetrischen Schlüssel-HMAC an.

Im Folgenden finden Sie Beispiele für Tokens, die aus einem signierten Wert erstellt wurden:

Ed25519-Signatur

Expires=160000000~FullPath~Signature=SIGNATURE_OF_SIGNED_VALUE

Dabei ist SIGNATURE_OF_SIGNED_VALUE die ED25519-Signatur des zuvor erstellten signierten Werts.

Symmetrischer Schlüssel-HMAC

Expires=160000000~FullPath~hmac=HMAC_OF_SIGNED_VALUE

Dabei ist HMAC_OF_SIGNED_VALUE der HMAC mit symmetrischem Schlüssel des zuvor erstellten signierten Werts.

In den vorherigen Beispielen wird FullPath im Token angegeben, aber der Wert aus dem Pfad, der im Wert mit Vorzeichen angegeben ist, nicht wiederholt wird. So können Sie den vollständigen Pfad der Anfrage signieren, ohne die Anfrage im Token zu duplizieren.

Beispiel für die Verwendung von URLPrefix

Sehen Sie sich das folgende Beispiel mit dem Feld URLPrefix an:

  • Angeforderter Artikel: http://example.com/tv/my-show/s01/e01/playlist.m3u8
  • Ablaufzeit: 160000000

Der vorzeichenbehaftete Wert ist:

Expires=160000000~URLPrefix=aHR0cDovL2V4YW1wbGUuY29tL3R2L215LXNob3cvczAxL2UwMS9wbGF5bGlzdC5tM3U4

Im vorherigen Beispiel haben wir den Pfad zum angeforderten Element ersetzt. http://example.com/tv/my-show/s01/e01/playlist.m3u8 durch den Pfad zum Element im websicheren Base64-Format, aHR0cDovL2V4YW1wbGUuY29tL3R2L215LXNob3cvczAxL2UwMS9wbGF5bGlzdC5tM3U4.

Zum Erstellen eines Tokens signieren Sie den signierten Wert entweder mit einer Ed25519-Signatur oder einem HMAC mit symmetrischem Schlüssel.

Im Folgenden finden Sie Beispiele für Tokens, die aus einem signierten Wert erstellt wurden:

Ed25519-Signatur

Expires=160000000~URLPrefix=aHR0cDovL2V4YW1wbGUuY29tL3R2L215LXNob3cvczAxL2UwMS9wbGF5bGlzdC5tM3U4~Signature=SIGNATURE_OF_SIGNED_VALUE

Dabei ist SIGNATURE_OF_SIGNED_VALUE die ED25519-Signatur des zuvor erstellten signierten Werts.

Symmetrischer Schlüssel-HMAC

Expires=160000000~URLPrefix=aHR0cDovL2V4YW1wbGUuY29tL3R2L215LXNob3cvczAxL2UwMS9wbGF5bGlzdC5tM3U4~hmac=HMAC_OF_SIGNED_VALUE

Dabei ist HMAC_OF_SIGNED_VALUE der HMAC mit symmetrischem Schlüssel des zuvor erstellten signierten Werts.

Beispiel für die Verwendung von Headers

Sehen Sie sich das folgende Beispiel mit dem Feld Headers an:

  • Angeforderter Artikel: http://example.com/tv/my-show/s01/e01/playlist.m3u8
  • Ablaufzeit: 160000000
  • PathGlobs-Wert: *
  • Erwartete Anfrageheader:
    • user-agent: browser
    • accept: text/html

Der vorzeichenbehaftete Wert ist:

Expires=160000000~PathGlobs=*~Headers=user-agent=browser,accept=text/html

Signieren Sie den signierten Wert entweder mit einer Ed25519-Signatur oder mit einem symmetrischen Schlüssel-HMAC an.

Im Folgenden finden Sie Beispiele für Tokens, die aus einem signierten Wert erstellt wurden:

Ed25519-Signatur

Expires=160000000~PathGlobs=*~Headers=user-agent,accept~Signature=SIGNATURE_OF_SIGNED_VALUE

Dabei ist SIGNATURE_OF_SIGNED_VALUE die ED25519-Signatur des zuvor erstellten signierten Werts.

Symmetrischer Schlüssel-HMAC

Expires=160000000~PathGlobs=*~Headers=user-agent,accept~hmac=HMAC_OF_SIGNED_VALUE

Dabei ist HMAC_OF_SIGNED_VALUE der HMAC mit dem symmetrischen Schlüssel -Wert angezeigt.

In den vorherigen Beispielen ist Headers=user-agent,accept im Token angegeben, die erwarteten Headerwerte werden jedoch nicht aus dem signierten Wert wiederholt. Dadurch können bestimmte Schlüssel/Wert-Paare des Anfrageheaders signieren, ohne die Werte zu duplizieren im Token.