跳转到内容
搜索文档

配置令牌身份验证

最后更新 查看 MarkdownAgent 设置

令牌身份验证可让您将文档、文件和媒体的访问限制给选定用户,而无需要求其注册。这有助于保护付费/受限内容免遭盗链和未经授权的分享。

配置令牌身份验证有两种选项:通过 Cloudflare Workers 或通过自定义规则。

选项 1:使用 Cloudflare Workers 配置

有关令牌身份验证的两种不同实现,请参阅以下 Cloudflare Workers 资源:

要开始使用 Workers,请参阅 Templates

选项 2:使用自定义规则配置

使用规则语言 is_timed_hmac_valid_v0() HMAC 验证函数,在自定义规则表达式中验证基于哈希的消息身份验证码(HMAC)令牌。

要验证令牌身份验证,请创建自定义规则,在规则表达式中调用 is_timed_hmac_valid_v0() 函数。可使用例如 Block 等操作。

示例规则

本示例说明一条规则:在特定主机名和 URL 路径上,对未通过 HMAC 密钥验证的任何访问者进行阻止。令牌身份验证所需详情包括:

  • 用于生成和验证 HMAC 的密钥(例如 mysecrettoken
  • 您希望进行身份验证的路径(例如 downloads.example.com/images/cat.jpg
  • 包含令牌的查询字符串参数名称(例如 verify
  • 令牌生命周期(秒)(例如 3 小时 = 10,800 秒)

考虑以下示例 URL:

downloads.example.com/images/cat.jpg?verify=1484063787-9JQB8vP1z0yc5DEBnH6JGWM3mBmvIeMrnnxFi3WtJLE%3D

其中:

  • /images/cat.jpg 表示资产路径——要验证的 HMAC 消息。
  • ?verify= 是资产路径与 HMAC 令牌签发时间戳之间的分隔符。
  • 1484063787 表示令牌签发时的时间戳,以 UNIX 时间(秒)表示。
  • 9JQB8vP1z0yc5DEBnH6JGWM3mBmvIeMrnnxFi3WtJLE%3D 是 Base64 编码的 MAC。

自定义规则的表达式类似于:

(http.host eq "downloads.example.com" and not is_timed_hmac_valid_v0("mysecrettoken", http.request.uri, 10800, http.request.timestamp.sec, 8))

此示例自定义规则的组成部分(使用前面的示例 URL)包括:

  • 令牌密钥 = mysecrettoken
  • 令牌生命周期 = 10800(10,800 秒 = 3 小时)
  • http.request.uri = /images/cat.jpg?verify=1484063787-9JQB8vP1z0yc5DEBnH6JGWM3mBmvIeMrnnxFi3WtJLE%3D
  • http.request.timestamp.sec = 1484071925(例如)
  • 分隔符长度:len("?verify=") = 8

is_timed_hmac_valid_v0() 函数将使用 mysecrettoken 密钥生成的 MAC 值与编码在 http.request.uri 中的值进行比较。

若 MAC 值匹配,且根据以下公式令牌尚未过期:

http.request.timestamp.sec < (<TIMESTAMP_ISSUED> + 10800)

则令牌有效,is_timed_hmac_valid_v0() 函数返回 true


HMAC 令牌生成

以下示例展示如何在源站服务器上,为上一节自定义规则所验证的路径生成令牌:

import hmac
import base64
import time
import urllib.parse
from hashlib import sha256

message = "/images/cat.jpg"
secret = "mysecrettoken"
separator = "verify"
timestamp = str(int(time.time()))
digest = hmac.new((secret).encode('utf8'), "{}{}".format(message, timestamp).encode('utf8'), sha256)
token = urllib.parse.quote_plus(base64.b64encode(digest.digest()))
print("{}={}-{}".format(separator, timestamp, token))
import hmac
import base64
import time
import urllib
from hashlib import sha256

message = "/images/cat.jpg"
secret = "mysecrettoken"
separator = "verify"
timestamp = str(int(time.time()))
digest = hmac.new(secret, message + timestamp, sha256)
param = urllib.urlencode({separator: '%s-%s' % (timestamp, base64.b64encode(digest.digest()))})
print(param)
<?php
$message = "/images/cat.jpg";
$secret = "mysecrettoken";
$separator = "verify";
$timestamp = time();
$token = urlencode(base64_encode(hash_hmac("sha256", $message . $timestamp, $secret, true)));
echo("{$separator}={$timestamp}-{$token}");

有关 JavaScript (JS) 或 TypeScript (TS) 的完整示例,请参阅 Workers 文档中的 Sign requests 示例。

由于该示例 JS/TS 实现与 is_timed_hmac_valid_v0() 函数兼容,使用所提供源代码进行身份验证的请求可通过 WAF 自定义规则和 is_timed_hmac_valid_v0() 函数进行验证。

这将生成类似如下的 URL 参数:

verify=1484063787-9JQB8vP1z0yc5DEBnH6JGWM3mBmvIeMrnnxFi3WtJLE%3D

您需要将此参数附加到受保护的 URL:

/images/cat.jpg?verify=1484063787-9JQB8vP1z0yc5DEBnH6JGWM3mBmvIeMrnnxFi3WtJLE%3D

测试生成的令牌参数

若您使用 Enterprise 计划,可通过以下方式测试源站服务器是否正确生成 URL:

  1. 将自定义规则操作设为 Log
  2. Security Events 中检查采样日志。

使用同一密钥保护多个路径

您可以使用同一密钥保护多个 URI 路径。

这在前面的示例中有说明,其中 http.request.uri 作为 MessageMAC 参数传递给验证函数。

由于 http.request.uri 包含资产路径,且该值会为每个请求提取,验证函数会使用同一密钥评估到 downloads.example.com 的所有请求 URI。

请注意,虽然您可以使用同一密钥验证多个路径,但必须为要验证的每条唯一消息生成一个 HMAC 令牌。

使用单个签名保护整个 URI 路径前缀

您可以用单个 HMAC 签名保护整个固定长度的 URI 路径前缀(也会使用同一密钥)。为此,请提供 URI 路径前缀(而不是完整 URI 路径)以及原始查询字符串,作为 is_timed_hmac_valid_v0() 函数的 MessageMAC 参数。

使用 substring() 函数从完整 URI 路径获取前缀。

在以下示例中,需要单个 HMAC 签名的 URI 路径前缀始终为 51 个字符长(x 为字符占位符):

/case-studies/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/

在此情况下,您需要对每个不同的 51 字符长度 URI 路径前缀使用不同的 HMAC 签名。

若要阻止未通过 HMAC 验证的案例研究文件请求,可创建类似如下的自定义规则:

规则表达式:

  (http.host eq "downloads.example.com" and starts_with(http.request.uri.path, "/case-studies") and not is_timed_hmac_valid_v0("mysecrettoken", concat(substring(http.request.uri.path, 0, 51), "?", http.request.uri.query), 10800, http.request.timestamp.sec, 1))

操作:

  • Block

有效传入请求的示例 URI 路径:

/case-studies/12345678-90ab-4cde-f012-3456789abcde/foobar-report.pdf?1755877101-5WOroVcDINdl2%2BQZxZFHJcJ6l%2Fep4HGIrX3DtSXzWO0%3D
/case-studies/12345678-90ab-4cde-f012-3456789abcde/acme-corp.pdf?1755877101-5WOroVcDINdl2%2BQZxZFHJcJ6l%2Fep4HGIrX3DtSXzWO0%3D
/case-studies/768bf477-22d5-4545-857d-b155510119ff/another-company-report.pdf?1755878057-jeMS5S1F3MIgxvL61UmiX4vODiWtuLfcPV6q%2B0Y3Rig%3D

前两个 URI 路径可使用同一 HMAC 签名,因为它们共享自定义规则验证的相同 51 字符前缀(/case-studies/12345678-90ab-4cde-f012-3456789abcde/)。

第三个 URI 路径需要不同的 HMAC 签名,因为前缀不同。

这篇文档对您有帮助吗?