一.referer
原理
在 http 协议请求中 header 里会带个 Referer 字段。通过图片服务器检查 Referer 是否来自规定的域名(白名单),而进行防盗链。 在浏览器中输入防盗链图片地址是能直接访问的。
简单实现防盗链图片
可以通过 nginx 配置白名单列表,不在白名单则返回 403 或者相应的处理(重定向到显示403的图片,等操作)
location ~* \.(gif|jpg|jpeg|png|bmp|swf|flv)$ {
valid_referers none blocked *.andyhu.com server_names ~\.google\. ~\.baidu\.;
if ($invalid_referer) {
return 403;
#rewrite ^/ http://www.xxx.com/403.jpg;
}
}
以上所有来自 *.andyhu.com 域名和域名中包含 google 和 baidu 的站点都可以访问当前站点的gif|jpg|jpeg|png|bmp|swf|flv文件资源。其他来源域(不在白名单列表)名访问则返回 403。如果被注释的 rewrite 则返回一张 403.jpg 的图片
显示第三方防盗链图片
顺这浏览器能直接访问防盗链图片的思路,不难发现,只要请求头 header 里面不携带 Referer 就能正常访问到防盗链的资源。
1.给某个资源添加 ReferrerPolicy 属性
例如:给图片资源添加 ReferrerPolicy 属性
<img src="xxxx.jpg" referrerPolicy="no-referrer" />
2.使用第三方代理
例如:通过第三方代理访问地址为https://p9-passport.byteacctimg.com/img/user-avatar/f9166aceb85b42133f48537808cef8eb~300x300.image 的图片
<img src="https://images.weserv.nl/?url=https://p9-passport.byteacctimg.com/img/user-avatar/f9166aceb85b42133f48537808cef8eb~300x300.image"/>
缺点: 不稳点,第三方代理可能在国内访问不稳定。
3.利用iframe伪造请求referer
function showImg( url ) {
var frameid = 'frameimg' + Math.random();
window.img = '<img id="img" src=\''+url+'?'+Math.random()+'\' />
<script>window.onload = function() { parent.document.getElementById
(\''+frameid+'\').height = document.getElementById(\'img\').height
+\'px\'; }<'+'/script>';
document.write('<iframe id="'+frameid+'" src="javascript:parent.img;
" frameBorder="0" scrolling="no" width="100%"></iframe>');
}
二.XMLHttpRequest
创建 XMLHttpRequest 对象
XMLHttpRequest 用于在后台与服务器交换数据。创建 XMLHttpRequest 对象的方法如下:
var xhr = new XMLHttpRequest ();
在 JavaScript 中,使用 XMLHttpRequest 对象的 open() 方法可以建立一个 HTTP 请求。用法如下:
xhr.open(method, url, async, username, password);
其中 xhr 表示 XMLHttpRequest 对象,open() 方法包含 5 个参数,说明如下:
- method:HTTP 请求方法,必须参数,值包括 POST、GET 和 HEAD,大小写不敏感。
- url:请求的 URL 字符串,必须参数,大部分浏览器仅支持同源请求。
- async:指定请求是否为异步方式,默认为 true。如果为 false,当状态改变时会立即调用 onreadystatechange 属性指定的回调函数。
- username:可选参数,如果服务器需要验证,该参数指定用户名,如果未指定,当服务器需要验证时,会弹出验证窗口。
- password:可选参数,验证信息中的密码部分,如果用户名为空,则该值将被忽略。
建立连接后,可以使用 send() 方法发送请求。用法如下:
xhr.send(body);
参数 body 表示将通过该请求发送的数据,如果不传递信息,可以设置为 null 或者省略。
发送请求后,可以使用 XMLHttpRequest 对象的 responseBody、responseStream、responseText 或 responseXML 属等待接收响应数据。
发送 GET 请求
在 JavaScript 中,发送 GET 请求简单、方便,适用于简单字符串,不适用于大容量或加密数据。实现方法:将包含查询字符串的 URL 传入 open() 方法,设置第 1 个参数值为 GET 即可。服务器能够通过查询字符串接收用户信息。
发送 POST 请求
在 JavaScript 中,POST 请求允许发送任意类型、长度的数据,多用于表单提交,以 send() 方法进行传递,而不以查询字符串的方式进行传递。POST 字符串与 GET 字符串的格式相同。格式如下:
send("name1=value1&name2=value2...");
获取 XML 数据
XMLHttpRequest 对象通过 responseText、responseBody、responseStream 或 responseXML 属性获取响应信息,说明如下表所示,它们都是只读属性。
在实际应用中,一般将格式设置为 XML、HTML、JSON 或其他纯文本格式。具体使用哪种响应格式,可以参考下面几条原则。
- 如果向页面中添加大块数据,选择 HTML 格式会比较方便。
- 如果需要协作开发,且项目庞杂,选择 XML 格式会更通用。
- 如果要检索复杂的数据,且结构复杂,那么选择 JSON 格式更加轻便。