70
微信
防盗链__存储空间管理_最佳实践_对象存储 OSS-阿里云
背景
A是网站站长,在A的网站的网页里有一些图片和音频视频的链接,这些静态资源都保存在阿里云对象存储OSS上。以图片为例子,A在OSS上存放的URL为https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png
。OSS资源外链地址见OSS 地址,这样的URL(不带签名)要求用户的Bucket权限为公开读权限。
B是另一个网站的站长,B在未经A允许的情况下,偷偷使用A的网站的图片资源,放置在自己网站的网页中,通过这种方法盗取空间和流量。在这样的情况下,第三方网站用户看到的是B的网站,网站用户不知道也不关心网站里的图片是来自于哪里。由于OSS是按照使用量来收费的,这样用户A在没有获取任何收益的情况下,反而承担了资源使用费用。
本文就是介绍类似A这样的用户将资源存放在OSS上后,如何设置防盗链来避免这样情况的发生。本文适用那些在网页中使用了OSS资源作为外链的用户。
实现方法
目前OSS提供的防盗链的实现方法主要有两种:
- 设置Referer。控制台、SDK都可以操作,适合不想写代码的用户,也适合喜欢开发的用户。
- 签名URL,适合喜欢开发的用户。
本文会给一个控制台设置Referer防盗链的具体事例,也会基于PHP SDK给一个动态生成签名URL防盗链的示例。
设置Referer
这里主要说明Referer是什么,OSS如何利用Referer做防盗链。
Referer是什么
Referer是HTTP Header的一部分,当浏览器向网站Web服务器发送请求的时候,一般会带上Referer,告诉服务器此次请求是从哪个页面链接过来的。以上面的例子来说,假如用户B的网站叫userdomain-steal,想盗链用户A的图片链接https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png
。A的网站域名为userdomain
。
假设盗链网站userdomain-steal的网页如下:
<html>
<p>This is a test</p>
<img src="https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png" />
</html>
假设源站为userdomain的网页如下:
<html>
<p>This is my test link from OSS URL</p>
<img src="https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png" />
</html>
当互联网用户用浏览器访问B的网站页面
https://userdomain-steal/index.html
,网页里链接是A的网站的图片。由于从一个域名(userdomain-steal)请求跳到了另一个域名(oss-cn-hangzhou.aliyuncs.com),浏览器就会在HTTP请求的Header中带上Referer,如图所示:可以看到浏览器在HTTP请求中的Referer为
https://userdomain-steal/index.html
。本文主要是使用chrome的开发者模式来查看网页请求的,如图:同样浏览器访问
https://userdomain/error.html
,也可以看到浏览器的Referer为https://userdomain/error.html
。如果浏览器直接输入地址,可以看到,请求中的Referer为空。
如果A没有在OSS进行任何Referer相关设置,以上三种情况都是可以访问用户A的图片链接。
OSS通过Referer防盗链的原理
通过上面的例子可以看到,浏览器在请求OSS资源的时候,如果发生页面跳转,浏览器会在请求中带入Referer,此时Referer的值为上一页面的URL,有的时候Referer也会为空。
针对这两种情况,OSS的Referer功能提供两种选择:
- 设置是否允许空Referer访问。不能单独设置,需要配合Referer白名单一起使用。
- 设置Referer白名单。
细节分析如下:
- 用户只有通过签名URL或者匿名访问object时,才会做防盗链验证。请求的Header中有“Authorization”字段的,不会做防盗链验证。
- 一个Bucket可以支持多个Referer参数。
- Referer参数支持通配符“*”和“?”。
- 用户可以设置允许空Referer的请求访问。
- 白名单为空时,不会检查Referer字段是否为空(不然所有的请求都会被拒绝,因为空Referer会被拒绝,对于非空Referer OSS在Referer白名单里也找不到)。
- 白名单不为空,且设置了”不允许Referer字段为空”的规则。则只有Referer属于白名单的请求被允许,其他请求(包括Referer为空的请求)会被拒绝。
- 白名单不为空,但设置了”允许Referer字段为空”的规则。则Referer为空的请求和符合白名单的请求会被允许,其他请求都会被拒绝。
- Bucket的三种权限(private,public-read,public-read-write)都会检查Referer字段。
通配符详解:
- 星号“*”:可以使用星号代替0个或多个字符。如果正在查找以AEW开头的一个文件,但不记得文件名其余部分,可以输入AEW,查找以AEW开头的所有文件类型的文件,如AEWT.txt、AEWU.EXE、AEWI.dll等。要缩小范围可以输入AEW.txt,查找以AEW开头的所有文件类型并.txt为扩展名的文件如AEWIP.txt、AEWDF.txt。
- 问号“?”:可以使用问号代替一个字符。如果输入love?,查找以love开头的一个字符结尾文件类型的文件,如lovey、lovei等。要缩小范围可以输入love?.doc,查找以love开头的一个字符结尾文件类型并.doc为扩展名的文件如lovey.doc、loveh.doc。
不同的Referer设置和防盗链效果
来看看Referer设置的效果:
1 只设置”不允许refer为空”
从控制台中来设置不允许refer为空,如图所示:
直接访问:发现可以访问,是防盗链失效了吗?不是的,因为”白名单为空时,不会检查Referer字段是否为空”,所以白名单为空的时候,这个设置无效。因此需要设置Referer白名单。
2 设置”不允许refer为空”的同时也设置Referer白名单
从前面例子中我们可以看到在浏览器的请求中Referer为当前页面的URL,所以需要知道网站会从哪几个URL跳转过来,然后进行配置。
Referfer白名单的设置规则:
- 例子中的Referer为
https://userdomain/error.html
,所以Referer白名单可以设置为https://userdomain/error.html
,但由于OSS的Referer检查是通过前缀匹配的,假如有其他网页比如https://userdomain/index.html
就访问不了,所以Referer白名单可以配置成https://userdomain/
。 - 假如还有其他域名比如
https://img.userdomain/index.html
也需要访问,那么Referer白名单应该加上https://*.userdomain/
。
这里两个都配置,如图所示:
做测试可以得到如下结果:
浏览器输入 | 预期 | 结果 |
---|---|---|
https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png | 直接访问,Referer为空,预期:不允许空Referer的请求,返回403 | 符合预期 |
https://userdomain/error.html | 请求来自于源站,预期:访问成功 | 符合预期 |
https://userdomain-steal/index.html | 请求来自于盗链网站。预期:OSS返回403,防盗链成功。 | 符合预期 |
https://img.userdomain/error.html | 请求来自于源站三级域名 | 符合预期 |
注意:
- 测试中提到的域名都是为了测试而假设的,和您实际的域名不一样,请注意区分。
- 如果Referer白名单只有
https://userdomain/
,浏览器模拟三级域名访问https://img.userdomain/error.html
的时候,三级域名无法匹配Referer白名单,OSS就会返回403。
3 设置”允许refer为空”的同时也设置Referer白名单
Referer白名单有https://*.userdomain/
和https://userdomain
。如图所示:
做测试可以得到如下结果:
浏览器输入 | 预期 | 结果 |
---|---|---|
https://referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png | 直接访问,Referer为空,预期:访问成功 | 符合预期 |
https://userdomain/error.html | 请求来自于源站,预期:访问成功 | 符合预期 |
https://userdomain-steal/index.html | 请求来自于盗链网站。预期:OSS返回403,防盗链成功。 | 符合预期 |
https://img.userdomain/error.html | 请求来自于源站三级域名 | 符合预期 |
如何在OSS里设置Referer
功能使用参考:
- API:Put Bucket Referer
- 控制台:防盗链设置
Referer防盗链的缺点
Referer防盗链的优点是设置简单,控制台即可操作。最大的缺点就是无法防止恶意伪造Referer,如果盗链是通过应用程序模拟HTTP请求,伪造Referer,则会绕过用户防盗链设置。如果对防盗链有更高要求的可以参考下面签名URL防盗链的描述。
签名URL
签名URL的原理和实现方法见OSS开发人员指南授权第三方下载。签名URL的实现步骤如下:
- 将Bucket的权限设置为私有读。
- 根据期望的超时时间(签名URL失效的时间)生成签名。
具体实现
- 安装PHP最新代码,参考PHP SDK文档。
实现生成签名URL并将其放在网页中,作为外链使用的简单示例如下:
<?php
require 'vendor/autoload.php';
#最新PHP提供的自动加载
use OSSOssClient;
#表示命名空间的使用
$accessKeyId="a5etodit71tlznjt3pdx7lch";
#AccessKeyId,需要使用用户自己的
$accessKeySecret="secret_key";
#AccessKeySecret,需要用用户自己的
$endpoint="oss-cn-hangzhou.aliyuncs.com";
#Endpoint,根据Bucket创建的区域来选择,本文中是杭州
$bucket = 'referer-test';
#Bucket,需要用用户自己的
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
$object = "aliyun-logo.png";
#需要签名的Object
$timeout = 300;
#期望链接失效的时间,这里表示从代码运行到这一行开始的当前时间往后300秒
$signedUrl = $ossClient->signUrl($bucket, $object, $timeout); #签名URL实现的函数
$img= $signedUrl;
#将签名URL动态放到图片资源中并打印出来
$my_html = "<html>";
$my_html .= "<img src="".$img. "" />";
$my_html .= "<p>".$img."</p>";
$my_html .= "</html>";
echo $my_html;
?>
- 通过浏览器访问多请求几次会发现签名的URL会变,这是正常的。主要是因为过期时间的改变导致的。这个过期时间是链接失效的时间,是以Unix time的形式展示的。例如:Expires=1448991693,可以将这个时间转换成本地时间。在Linux下的命令为
date -d@1448991693
,也可以在网络上找工具自行转换。
特别说明
签名URL可以和Referer白名单功能一起使用。
如果签名URL失效的时间限制在分钟内,盗链用户即使伪造了Referer也必须拿到签名的URL,且必须在有效的时间内才能盗链成功。相比只使用Referer来说,增加了盗链的难度。也就是说签名URL配合Referer白名单功能,可以增加防盗链的效果。
防盗链总结
基于OSS的防盗链最佳实践点如下:
- 使用三级域名URL,例如
referer-test.oss-cn-hangzhou.aliyuncs.com/aliyun-logo.png
,安全性比绑定二级域名更高。三级域名方式能够提供Bucket级别的清洗和隔离,能够应对被盗链后的流量暴涨的情况,也能避免不同Bucket间的互相影响,最终提高业务可用性。 - 如果使用自定义域名作为连接,CNAME也请绑定到三级域名,规则是bucket + endpoint。假如您的bucket名为test,三级域名则为
test.oss-cn-hangzhou.aliyuncs.com
。 - 对Bucket设定尽可能严格的权限类别。例如提供公网服务的Bucket设置为public-read或private,禁止设置为public-read-write。Bucket权限参见访问控制
- 对访问来源进行验证,根据需要设置合适的Referer白名单。
- 如果需要更严格的防盗链方案,请参考签名的URL方案。
- 记录Bucket访问日志,能够及时发现盗链活动和验证防盗链方案的有效性。 访问日志参见 设置访问日志记录。
常见问题及解决方案
在OSS控制台设置了防盗链,一直不生效,但页面可以防而播放器不可以,请问为什么?怎么解决?
目前设置防盗链不生效的主要问题集中于视频和音频文件,在使用诸如Windows Media Player、Flash Player等播放器后,在请求OSS资源的时候传递的Referer为空,这就造成防盗链的失效,不仅仅把别人防住了,也把自己给防住了。针对这种情况,可以参考上面提到的签名URL防盗链的方法。
Referer是什么?怎样才会带上?如果遇到HTTPS怎么办,不需要添加别的了吗,比如逗号之类的?
Referer是HTTP协议中的请求头,在跨页面访问的时候会带上。需要看看浏览器请求的Referer是
https://
还是https://
,一般是https://
。如何生成签名URL?AccessKeySecret放在客户端里的安全性?
签名URL的方法参见各个SDK文档。AccessKeySecret这种不建议直接放在客户端,RAM提供了STS服务可以解决这个问题。也可以参考RAM和STS指南。
例如要写
a.baidu.com
和b.baidu.com
,这两个用通配符(*,?) 如何写?可以写成
https://*.baidu.com
,对于这种单字符的也可以写成https://?.baidu.com
*.domain.com 可以匹配二级域名,但无法匹配 domain.com,另外添加一行 domain.com 也没效果,如何配置?
注意一般的referer中会带http这样的参数,可以通过chrome的开发者模式观察下请求的Referer是什么,然后再具体设置。这里可能是忘了写
https://
,应该为https://domain.com
如果防盗链没有生效怎么办?
推荐使用chrome来查看。打开开发者模式,点击网页,查看HTTP请求中的
Referer
具体值是什么,对应在OSS中设置的Referer
,是否能匹配上。如果还是解决不了,请提工单。
最后更新:2016-11-23 16:04:09
上一篇:
跨域资源共享(CORS)__存储空间管理_最佳实践_对象存储 OSS-阿里云
下一篇:
权限管理概述__权限管理_最佳实践_对象存储 OSS-阿里云
规则引擎移动定向营销版本公测服务协议__相关协议_平台介绍_数加平台介绍-阿里云
.gov.cn 域名的意义及注册限制__域名注册规则_产品选型_域名-阿里云
ClearAccountAlias__安全设置接口_RAM API文档_访问控制-阿里云
通知__使用须知_用户指南_弹性伸缩-阿里云
PHP教程__sdk_数据风控-阿里云
VPC中的ECS访问经典网络中的RDS失败__异常处理_用户指南_专有网络 VPC-阿里云
合作伙伴账号下找不到某域名的原因__渠道商下客户问题_渠道合作伙伴_合作伙伴-阿里云
有关Bucket命令__osscmd_常用工具_对象存储 OSS-阿里云
阿里云栖大会明日开幕,9月重卡销量再增89%
如何变更发票信息__发票问题_发票及合同_财务-阿里云
相关内容
常见错误说明__附录_大数据计算服务-阿里云
发送短信接口__API使用手册_短信服务-阿里云
接口文档__Android_安全组件教程_移动安全-阿里云
运营商错误码(联通)__常见问题_短信服务-阿里云
设置短信模板__使用手册_短信服务-阿里云
OSS 权限问题及排查__常见错误及排除_最佳实践_对象存储 OSS-阿里云
消息通知__操作指南_批量计算-阿里云
设备端快速接入(MQTT)__快速开始_阿里云物联网套件-阿里云
查询API调用流量数据__API管理相关接口_API_API 网关-阿里云
使用STS访问__JavaScript-SDK_SDK 参考_对象存储 OSS-阿里云