You need to enable JavaScript to run this app.
导航
URL 鉴权概述
最近更新时间:2024.07.24 21:21:45首次发布时间:2023.03.20 19:52:02

视频点播提供 Referer 黑白名单、IP 黑白名单等功能对访客进行过滤。但是在某些情况下,Referer 和 IP 可以被伪造,容易造成站点资源被恶意盗用。如果您对于站点内容的安全性有很高的要求,可以采用 URL 鉴权。本文为您介绍如何在视频点播控制台开启和配置 URL 鉴权。

URL 鉴权流程

下图展示了视频点播 URL 鉴权的整体流程:
图片
具体步骤说明如下:

  1. 生成鉴权 URL:应用服务端使用共享的密钥和鉴权算法,对 URL 进行签名。签名过程通常涉及将 URL 的部分或全部参数与密钥进行加密或摘要。签名后,应用服务端将鉴权参数添加到 URL 中,形成完整的请求 URL。
  2. 下发鉴权 URL:应用服务端将带鉴权信息的请求 URL 下发给应用客户端。
  3. 发送资源请求:应用客户端使用带鉴权信息的请求 URL 向视频点播 CDN 节点发起资源请求。
  4. 校验鉴权参数:CDN 节点使用与应用服务端共享的密钥和鉴权算法对鉴权参数进行校验。校验的过程通常涉及判断鉴权 URL 的有效期,以及将请求参数与鉴权参数一起进行签名,并与请求中的鉴权参数进行比对。
    • 如校验通过,CDN 节点将根据请求参数,从缓存中或源服务器获取资源,并将其返回给应用客户端。
    • 如校验失败,CDN 节点返回 403 错误,拒绝访问。

在这个流程中,应用客户端负责发起请求,应用服务端负责生成鉴权 URL,CDN 节点负责接收请求并进行鉴权信息的校验。鉴权信息的生成和校验依赖于共享的密钥和鉴权算法,确保了请求的合法性和安全性。通过这种方式,您可以有效地保护 CDN 资源免受未经授权的访问。

适用范围

URL 鉴权适用于点播加速域名和自定义源站加速域名。其中:

  • 点播加速域名的 URL 鉴权支持配置 A 类型。
  • 自定义源站加速域名的 URL 鉴权支持配置 A 类型、B 类型、C 类型、D 类型和 E 类型。

点播加速域名

按照以下步骤为点播加速域名开启并配置 A 类型的 URL 鉴权:

  1. 登录视频点播控制台,进入指定空间。

  2. 单击左侧导航栏分发加速设置 > 域名管理

  3. 单击点播加速域名页签,单击操作列的配置按钮。

  4. 点播加速域名配置页面,单击访问控制页签。

  5. 单击页面下方修改配置按钮。

  6. URL 鉴权区域,开启并配置 URL 鉴权功能。
    图片
    详细的参数信息如下表所示。

    参数

    说明

    类型

    A 类型

    生效对象

    表示对哪些文件的请求需要被鉴权。您至少需要添加一个规则,最多可以添加 10 个。
    您可以指定多个规则之间的关系:

    • 默认是任一,表示匹配任何一个规则的请求就会被鉴权。
    • 所有表示只有匹配所有规则的请求才会被鉴权。

    每条规则包含以下配置:

    • 条件类型:支持以下选项:
      • 文件目录:规则应用于特定目录下的所有文件。
      • 文件后缀:规则应用于特定后缀名的所有文件。
      • 文件全路径匹配:规则应用于特定文件。
    • 是否匹配:可设为匹配不匹配
    • 规则:根据规则类型,输入规则的内容。长度不能超过 1,024 个字符。不能包含以下字符:连续斜杠(//)、空格、美元符号($)、问号(?)、Delete(ASCII code 127)。不同规则类型的具体要求如下:
      • 如果规则类型是文件后缀,规则内容必须是一个或者多个以分号(;)分隔的文件后缀。文件后缀无需以句点(.)开头。示例:png;txt
      • 如果规则类型是文件目录,规则内容必须是一个或者多个以分号(;)分隔的目录路径。目录路径必须以斜杠(/)开头和结尾。示例:/chs/foods/;/us/birds/
      • 如果规则类型是文件全路径,规则内容必须是一个或者多个以分号(;)分隔的文件路径。文件路径必须以斜杠(/)开头,可以包含星号(*)用来表示一个或者多个字符。示例:/chs/foods/local*sets;/us/birds/chickadee

    签名主 Key

    主密钥。支持通过以下两种方式设置签名主 Key:

    • 单击随机生成按钮。系统会自动生成 32 位随机字符串。
    • 自定义签名 key。仅支持可见 ASCII 码,长度为 6~40 个字符。

    签名备 Key

    备密钥。支持通过以下两种方式设置签名备 Key:

    • 单击随机生成按钮。系统会自动生成 32 位随机字符串。
    • 自定义签名 key。仅支持可见 ASCII 码,长度限制为 6-40 个字符。

    说明

    对线上业务域名变更 URL 鉴权时,建议在过渡期使用备 Key,避免业务中断。

    签名参数

    固定为 auth_key

    时间格式

    固定为十进制(Unix 时间戳)

    m3u8 改写

    表示在响应 .m3u8 文件的请求时,是否对 .m3u8 文件中每个分片文件的 URL 添加签名参数。每个分片 URL 的签名是基于改写后分片 URL,使用签名规则计算的。开启该配置后,您还可进行以下配置:

    • 分片 URL 原参数:在改写分片 URL 时是否保留 URL 中原有的参数。默认保留。
    • m3u8 非签名参数:是否将来自该 M3U8 文件请求的不表示签名的查询参数添加到分片 URL 中。默认不继承。

    说明

    • 对于点播加速域名,m3u8 改写默认开启。
    • 对于自定义源站加速域名,m3u8 改写默认关闭。

    注意

    对于点播加速域名的 A 类型 URL 鉴权,不支持在控制台设置有效时长。点播加速域名 A 类型的签名计算规则,请见签名计算

自定义源站加速域名

按照以下步骤为自定义源站加速域名开启并配置 URL 鉴权:

  1. 登录视频点播控制台,进入指定空间。
  2. 单击左侧导航栏分发加速设置 > 域名管理
  3. 单击自定义源站加速域名页签,单击操作列的配置按钮。
  4. 自定义源站加速域名配置页面,单击访问控制页签。
  5. 单击页面下方修改配置按钮。
  6. URL 鉴权区域,选择不同类型的 URL 鉴权,开启并配置 URL 鉴权功能。具体操作请参见如下文档:

常见问题

时间戳防盗链功能与 URL 鉴权功能均会影响视频播放地址的有效时长,这两者区别是什么?

时间戳防盗链功能决定了通过 GetPlayInfo 接口从视频点播服务获取到的视频播放地址的有效时长。URL 鉴权功能中设置的有效时长决定的则是视频点播 CDN 服务生成的 URL 的有效时长。
如果您同时配置了时间戳防盗链和URL鉴权,那么会存在以下两种情况:

  • 如果您的视频播放地址是通过 GetPlayInfo 接口获取的,那么实际有效时长则为时间戳防盗链中设置的有效时长 + URL 鉴权中设置的有效时长。
  • 如果您的视频播放地址是自行拼接得到的,那么实际有效时长将只取决于 URL 鉴权中设置的有效时长。

签名 Demo

为方便您快速进行签名计算,视频点播提供了多种语言的签名 Demo,演示如何根据给定的密钥和其他参数,生成不同类型的带签名的 URL。

package main

import (
        "crypto/md5"
        "encoding/hex"
        "fmt"
        "math/rand"
        "regexp"
        "strconv"
        "time"
)

func splitUrl(url string) []string {
        reg := regexp.MustCompile("^(http://|https://)?([^/?]+)(/[^?]*)?(\\?.*)?$")
        return reg.FindStringSubmatch(url)
}

func getMd5(text string) string {
        hashByte := md5.Sum([]byte(text))
        return hex.EncodeToString(hashByte[:])
}

func getRandomString(length int) string {
        b := make([]byte, length)
        rand.Read(b)
        return fmt.Sprintf("%x", b)[:length]
}

func GenTypeAUrl(url string, key string, signName string, uid string, ts int64) string {
        params := splitUrl(url)
        scheme, host, path, args := params[1], params[2], params[3], params[4]
        randstr := getRandomString(10)
        text := fmt.Sprintf("%s-%d-%s-%s-%s", path, ts, randstr, uid, key)
        hash := getMd5(text)
        authArg := fmt.Sprintf("%s=%d-%s-%s-%s", signName, ts, randstr, uid, hash)
        if args == "" {
                return fmt.Sprintf("%s%s%s?%s", scheme, host, path, authArg)
        } else {
                return fmt.Sprintf("%s%s%s%s&%s", scheme, host, path, args, authArg)
        }
}

func GenTypeBUrl(url string, key string, ts int64) string {
        params := splitUrl(url)
        scheme, host, path, args := params[1], params[2], params[3], params[4]
        tsStr := time.Unix(ts, 0).Format("200601021504")
        text := fmt.Sprintf("%s%s%s", key, tsStr, path)
        hash := getMd5(text)
        return fmt.Sprintf("%s%s/%s/%s%s%s", scheme, host, tsStr, hash, path, args)
}

func GenTypeCUrl(url string, key string, ts int64) string {
        params := splitUrl(url)
        scheme, host, path, args := params[1], params[2], params[3], params[4]
        tsStr := strconv.FormatInt(ts, 16)
        text := fmt.Sprintf("%s%s%s", key, path, tsStr)
        hash := getMd5(text)
        return fmt.Sprintf("%s%s/%s/%s%s%s", scheme, host, hash, tsStr, path, args)
}

func GenTypeDUrl(url, key, signName, timeName string, ts int64, base int) string {
        params := splitUrl(url)
        scheme, host, path, args := params[1], params[2], params[3], params[4]
        tsStr := strconv.FormatInt(ts, base)
        text := fmt.Sprintf("%s%s%s", key, path, tsStr)
        hash := getMd5(text)
        authArg := fmt.Sprintf("%s=%s&%s=%s", signName, hash, timeName, tsStr)
        if args == "" {
                return fmt.Sprintf("%s%s%s?%s", scheme, host, path, authArg)
        } else {
                return fmt.Sprintf("%s%s%s%s&%s", scheme, host, path, args, authArg)
        }
}

// GenTypeEUrl Genrate signed url by custom rule(eg.:key+domain+uri+timestamp)
func GenTypeEUrl(url, key, signName, tsName string, ts int64, base int) string {
        params := splitUrl(url)
        scheme, domain, uri, args := params[1], params[2], params[3], params[4]
        tsStr := strconv.FormatInt(ts, base)
        text := fmt.Sprintf("%s%s%s%s", key, domain, uri, tsStr)
        hash := getMd5(text)
        authArg := fmt.Sprintf("%s=%s&%s=%s", signName, hash, tsName, tsStr)
        if args == "" {
                return fmt.Sprintf("%s%s%s?%s", scheme, domain, uri, authArg)
        } else {
                return fmt.Sprintf("%s%s%s%s&%s", scheme, domain, uri, args, authArg)
        }
}

func init() {
        rand.Seed(time.Now().UnixNano())
}

func main() {
        var url = "http://www.test.com/a.txt?a=b&c=d"
        var primaryKey = "primary123456"
        var signName = "auth_key"
        var timeName = "t"
        var uid = "0"
        var ts = time.Now().Unix() + 3600 //默认一小时过期

        typeAUrl := GenTypeAUrl(url, primaryKey, signName, uid, ts)
        typeBUrl := GenTypeBUrl(url, primaryKey, ts)
        typeCUrl := GenTypeCUrl(url, primaryKey, ts)
        typeDUrl := GenTypeDUrl(url, primaryKey, signName, timeName, ts, 10)
        typeEUrl := GenTypeEUrl(url, primaryKey, signName, timeName, ts, 10)

        fmt.Println("OriginUrl: ", url)
        fmt.Println("TypeA: ", typeAUrl)
        fmt.Println("TypeB: ", typeBUrl)
        fmt.Println("TypeC: ", typeCUrl)
        fmt.Println("TypeD: ", typeDUrl)
        fmt.Println("TypeE: ", typeEUrl)
}