前言
随着互联网的高速发展,无论是移动 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 防盗链。