大家好,又见面了,我是你们的朋友全栈君。
防盗链原理:
http标准协议中有专门的字段记录referer
1、他可以追溯到请求时从哪个网站链接过来的。
//小例子
这个头信息指示所指向的 Web 页的 URL。例如,如果您在网页 1,点击一个链接到网页 2,
当浏览器请求网页 2 时,网页 1 的 URL 就会包含在 Referer 头信息中。
2、来对于资源文件,可以跟踪到包含显示他的网页地址是什么。
因此很多防盗链方法都是基于这个Referer字段
//而User-Agent 是判断爬虫和浏览器的一个原因
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'Referer': 'http://****'
一、事情经过
在一开始,我打算将其他网站的图片放在自己的网站(http://localhost…)上显示.
<img src="http://pic6.iqiyipic.com/image/20200215/f6/f9/a_100280816_m_601_m2.jpg"/>
结果却是返回403 Forbidden (即:没有权限访问此站),无法在自己的网站上加载出图片.
然后我以为是链接失效了,然后我复制该链接到浏览器上直接访问,发现可以正常加载图片,
还有在本地(file://…)打开也能正常显示图片.
然后我就纳闷了,为什么同一个html文件(都是加载同一条链接).
我使用(http协议)打开,就返回403,我本地打开(file协议)就可以返回正常图片,
我想src链接是一样的,那肯定是两种请求方式(http和file)的不同让他们的服务器识别了,
针对不同的请求返回不同的结果(其实是通过Referer字段识别的)
二、寻找原因
然后为了查看两种请求方式的不同,我就自己写了一个node服务器(其实直接在浏览器上查看请求头的也是可以的,不过我是找到原因以后才知道的)
var express = require('express'); //引入express模块
var app = express(); //创建express的实例
app.get('/app', function(req, res){
console.log(req.headers); //打印请求头
res.send('Hello,myServer'); //服务器响应请求
});
app.listen(3000,function(){
//监听3000端口
console.log("Server running at 3000 port");
});
写了一个客户端(html代码省略)
<script type="text/javascript">
$(function () {
$.ajax({
url: "http://localhost:3000/app", //请求业务数据
type: "GET",
success: function (result) {
console.log(result+'3000');
}
});
});
</script>
(在本地直接打开会显示跨域,不要紧,因为请求(这里指简单请求,简单请求和复杂请求的区别)
已经发出去了,不管有没有跨域浏览器都会发送请求,然后浏览器通过接受到返回结果发现请求头没有
‘Access-Control-Allow-Origin’ ‘*’ 才显示跨域的,也就是说数据发过来了,浏览器就是不给你显示)
本地打开(file:///)显示结果
而借助nginx打开的(http://)
url: "http://localhost/app", //将url请求路径修改
#nginx.config配置转发路径(这样就不会显示跨域了,还能将结果返回浏览器)
location /app {
proxy_pass http://192.168.0.103:3000; #转发地址
}
结果
从上面两幅图就可以看出,本地请求没有referer请求字段,而http请求却有
然后查阅得知:正是referer起到了防盗链的作用。防止其他网站加载他的的图片
三、解决方法
因为浏览器限制,不能手动添加和修改referer请求头
所以只利用nginx来转发请求,并重新设置referer字段
location /* {
proxy_set_header referer ''; #设置为空,或者该请求路径允许的referer字段路径
proxy_pass http://........; #转发地址
}
四、新增方法
js使用iframe跳过防盗链
<script type="text/javascript">
function showImg( url ) {
var frameid = 'frameimg' + Math.random();
//使用window(全局对象)来声明,全局对象的属性也是全局变量
window.imgWindow = '<img id="imgId" src=\''+url+'?'+Math.random()+'\' /><script>window.onload = function() { parent.document.getElementById(\''+frameid+'\').height = document.getElementById(\'imgId\').height+\'px\'; }<'+'/script>';
document.write('<iframe id="'+frameid+'" src="javascript:parent.imgWindow;" frameBorder="0" scrolling="no" width="100%"></iframe>');
}
</script>
//调用
<script type="text/javascript">showImg('图片地址');</script>
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163487.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...