前言

随着互联网的高速发展,无论是移动 APP 还是 WEB 站点,访问的安全问题始终困扰着内容提供商。CDN ( Content Delivery Network,内容分发网络 ) 服务作为当今互联网世界的快递专家扮演着更重要的角色,也承担了更多的使命,在使用 CDN 服务的过程中,内容提供商提出了如下要求:


  • 内容资源在经过 CDN 分发时,不被其他人恶意引用或者被非法下载

  • 确保在使用 CDN 服务的过程中避免产生不必要的 CDN 带宽浪费,从而节约成本

  • CDN 服务提供商提供的防盗链措施不容易被破解和绕过

基于以上要求,又拍云作为云 CDN 厂商的代表,认为传统的 IP 禁用、referer 防盗链、User-Agent 防盗链、地区访问控制等防盗链措施已经无法完全满足用户要求,今天我们专门来介绍一下更加高级的 token 防盗链。文章的末尾,为了实现更加灵活的 token 防盗链配置,我们引入了又拍云自定义 rewrite 功能。


如何实现


Token 防盗链是通过对时间有关的字符串进行签名,将时间、签名信息通过一定的方式传递给 CDN 节点服务器作为判定依据,CDN 边缘节点依据约定的算法判断来访的 URL 是否有访问权限。如果通过,执行下一步;如果不通过,响应 HTTP 403 状态码或者通过 302 跳转到其他 URL。


1、签名参数


etime: URL 过期的时间,必须是 UNIX TIME 格式,如:2017/3/9 9:19:0 -> 1489022340

secret: 和 CDN 平台约定的签名密钥,需要在 CDN 管理控制台配置,如下图(服务-> 全网加速 -> 配置 -> 防盗链 -> Token 防盗链)所示:

URI:请求 URL 的路径部分(不包含 ? 及后面的 Query String),如客户端访问的外链地址为 http://xxx.b0.upaiyun.com/path/to/a.jpg?version=1.0,那么 URI 部分则为:/path/to/a.jpg


2、算法说明


sign = MD5( secret & etime & URI )

_upt = sign { 中间 8 位 }+etime

_upt = MD5( secret & etime & URI ){ 中间 8 位 } + etime


举个例子:假设当前的 UNIX TIME 时间为:1370000000,某图片资源(例如:http://test.example.com/dir/pic.jpg)10 分钟有效,则:


etime = 1370000000 + 600 = 1370000600

uri = '/dir/pic.jpg'

sign = MD5( secret & etime & URI ) = xxxxxxxxxxxxabcdefghyyyyyyyyyyyy

_upt = MD5( secret & etime & URI ){ 中间 8 位 } + etime = abcdefgh1370000600


最后经过客户端业务服务器生成的 URL 为:


http://test.example.com/dir/pic.jpg?_upt=abcdefgh137000060


3、业务流程


如下图所示,整个 token 防盗链的实现需要如下几个部分来配合:

1)客户端:负责发送原始请求给客户端业务服务器以及发送带签名的 URL 给 CDN 节点进行验证

2)业务服务器:根据约定的算法生成带 _upt 参数的 URL 返回给客户端

3)CDN 节点:负责和客户端进行时间、签名校验


4、实现方式


1)客户端业务服务器生成验证信息

验证信息的生成由业务服务器负责,具体的加密过程需要确认如下事项:

  • 确认过期时间的格式,默认采用 UNIX 时间戳格式

  • 确认验证信息中的密文,用户计算验证信息,需要和 CDN 平台约定

  • 确认验证信息时加入的参数,默认为 URL 的路径部分

  • 根据上文的算法说明计算验证信息,其中请求 URL 中的验证参数为 _upt


多语言生成 token 的例子参见 Github 地址:


https://github.com/upyun/token-examples


2)又拍云 CDN 节点验证过程


  • 根据约定解析取出过期时间,和当前 CDN 节点服务器时间进行比较,确认请求是否过期

  • 根据上文约定好的算法计算方式,计算出 MD5 加密串后,和 URL 中的加密串进行比较,验证加密串是否一致

  • 如果以上两个步骤都验证通过,请求才会被认为是合法的,这时 CDN 会请求资源响应给客户端,否则会被认为是非法请求,直接响应 HTTP status code 403

扩展阅读


为了兼容其他厂商的 token 防盗链规则或者需要实现更加复杂的 token 防盗链,结合又拍云自定义 rewrite 功能就可以快速实现,无需定制化,一条简单的规则就可以满足要求。


例如,如下 URL 为某 CDN 厂商的和用户约定的访问 URL 规则:

http://example.com/test.png?key=1b7915a3059bf510500316ed262b58da&time=575f3027


此时,只需要结合又拍云自定义 rewrite 配置一条规则即可满足要求,规则如下所示:


$WHEN($NOT($ALL($GT($INT($_GET_, 16), &_Time),$EQ($_GET_key, $MD5(test $_URI $_HOST $_GET_TIME)))))$EXIT(403)


规则解释:上面的规则主要是比较 time 和 key 的值,只有当过期时间大于本地时间,同时 key 的值和 CDN节点计算的 MD5 值一致,则验证通过;当不满足的时候,会返回 403。


总之,结合又拍云自定义 rewrite 功能,可以快速实现超强版的 token 防盗链。