117
时间戳防盗链

操作说明

登录,进入控制台->cdn->域名管理->配置->访问控制

时间戳防盗链修改配置

时间戳防盗链:默认为关闭,开启时,会同时生成两组可用的key,用户需先按照文档说明在代码中将key配置进您的url,再进行格式检查,然后确认开启;还可以自定义输入key,支持输入备用key且不能与主key相同;同时需要输入检查url,以保证鉴权服务正常可用,以免影响服务。

算法说明

基于时间戳的防盗链是通过对时间有关的字符串进行签名,将时间、签名通过一定的方式传递给 cdn 服务器作为判定依据,cdn 边缘节点根据约定的算法判断来访url是否有访问权限。

通过,执行下一步;不通过,响应 http status code 403。

若同时配置了 referer、ua防盗链、时间戳防盗链,有一项不满足条件,即为不通过,响应 403 。

签名参数

  • t:url 过期时间。按 unix_time 的 16进制小写形式表示。 如 2015-08-01 00:00:00 –> 1438358400 –> 55bb9b80
  • key:在开启时间戳防盗链时,可以由使用:(控制台->cdn->域名管理->访问控制->时间戳防盗链),使用其中一个即可。也可以自行使用算法生成。
  • path:访问资源的 url 中的路径部分,例如:访问的url为 http://xxx.yyy.com/dir1/dir2/vodfile.mp4?v=1.1,则 path = /dir1/dir2/vodfile.mp4(注意不含 querystring 部分)

签名算法

  • 签名原始字符串 s = key url_encode(path) t 。斜线 / 不编码。
  • 签名 sign = md5(s).to_lower(),to_lower 指将字符串转换为小写;

注:本文所提到的 url_encode 算法。

签名参数传递方式

作为url查询参数。

例如原始访问的url为: http://xxx.yyy.com/dir1/dir2/vodfile.mp4?v=1.1

最终形成的访问url为: http://xxx.yyy.com/dir1/dir2/vodfile.mp4?v=1.1&sign=&t=

  • 签名参数 sign、 t ,sign 在前,t 在后;
  • 替换为对应的值, 实际url中不含<> ;

访问url

访问 url 的 path 部分也需要 url_encode,其算法与签名时使用 url_encode 算法一致。斜线 / 不编码。

访问 url 为:

scheme"://"hosturl_encode(path) query_part

http://xxx.yyy.com/dir1/dir2/vodfile.mp4?v=1.1&sign=19eb212771e87cc3d478b9f32d6c7bf9&t=55bb9b80
http://xxx.yyy.com/dir1/中文/vodfile.mp4?v=1.2&sign=6356bca0d2aecf7211003e468861f5ea&t=55bb9b80

注:

  1. 本文所提到的 url_encode 算法,斜线 / 不编码。
  2. 访问 url 的 path 部分推荐按 url_encode 编码,如下例。
示例
例1:

url http://xxx.yyy.com/dir1/dir2/vodfile.mp4?v=1.1 ,假设 key = 12345678 ;过期时间为 2015-08-01 00:00:00 ,即 1438358400 ,也就是 t = 55bb9b80s = 12345678/dir1/dir2/vodfile.mp455bb9b80sign = 19eb212771e87cc3d478b9f32d6c7bf9 , 访问 url 为:

http://xxx.yyy.com/dir1/dir2/vodfile.mp4?v=1.1&sign=19eb212771e87cc3d478b9f32d6c7bf9&t=55bb9b80

之后将 url 地址填写在上图中的 检查url 处验证。

例2:

url http://xxx.yyy.com/dir1/中文/vodfile.mp4?v=1.2 ,假设 key = 12345678t = 55bb9b80s = 12345678/dir1/中文/vodfile.mp455bb9b80sign = 6356bca0d2aecf7211003e468861f5ea ,访问 url 为:

http://xxx.yyy.com/dir1/中文/vodfile.mp4?v=1.2&sign=6356bca0d2aecf7211003e468861f5ea&t=55bb9b80

之后将 url 地址填写在上图中的 检查url 处验证。

服务端验证

服务端拿到原始的 url ,直接解析出 host, path, sign, t ,再签名。

算法: s = key path t,sign = md5(s).to_lower()

注意此处没有 url_encode 操作。

原始的 url 指未经 url_decoded 的内容。

以 nginx 为例说明:

浏览器发出实际请求url: http://example.com/foobar/hello world

nginx变量 $uri: http://example.com/foobar/hello world

nginx变量 $request_uri: http://example.com/foobar/hello world

原始的 url 内容和 $request_uri 内容一致。

要求验证签名时使用 $request_uri ,此值为原始值,内容是正确的经过 url encode 的内容,所以 path 不用编码。

服务端不能使用 $uri 获取各参数,然后再调用 url_encode 来获取待签名的 path。path url_encode 后再 url_decode,获得的内容与原 path 可能不一样。

http://example.com/foobar/hello world
http://example.com/foobar/hello+world
http://example.com/foobar/hello+world

以上三个url都是合法的访问同一资源的链接。相同 key 、t,执行签名后会有三个不同的值。 + url_decode 再 url_encode 可能得到 +,导致签名不一致。