前几天,把微信公众号上的内容复制到网站的时候,一开始还好好的,发布到线上服务器的时候,出现了文章里面的图片全部被替换成了“此图片来自微信公众平台 未经允许不可引用”的图片,根据过往经验,是腾讯使用了防盗链的机制。
一、网站为什么会使用防盗链,防盗链的原理是什么?
网站做防盗链主要是为了防止网站的图片,视频等静态资源被第三方网站引用,给服务器造成不必要的资源(内存,CPU)和带宽(网速,流量)消耗。
防盗链的原理主要是使用img等标签引用外部图片的时候,通常默认会带有HTTP请求的Referer头部,服务端就可以通过这个HTTP请求的Referer头部,来判断来源地址是否存在于引用白名单里面,如果在白名单,就显示正常的图片,如果不在,就返回防盗链图片。
二、如何解决这个问题?
解决这个问题,一般有三种方案。
①、通过网站的编辑器(前端JavaScript)判断复制过来的文章是否存在外链图片,如果存在,就提交给后端(如php或者Java之类的)把这张图片下载到服务器,并改变图片路径为本地服务器路径(如果外链图片过多或者过大,容易造成本地服务器资源和带宽的消耗)。
②、在引用该外链图片的时候,通过网站的后端去访问这张图片的URL,然后通过服务器中转,并呈现目标图片给用户前端访问(如果外链图片过多或者过大,容易造成本地服务器资源和带宽的消耗,且如果通过服务器访问外链图片次数过多,容易被对方的网站管理员发现,并封ip)。
③、前面说过,目标服务器是通过img等标签请求的时候,默认带的Referer头部参数来判断是否外链访问,那么,前端访问这张图片的时候,把默认的Referer头部去掉,就可以实现绕过防盗链的效果了。
三、如何去掉默认的Referer头部?
一般有两种方案:
①、在文章页面的头部加入以下这行代码,大概意思是全局定义该页面不发送任何Referer头信息(这个方式是有效的,但我不想要全局定义)。
<meta name="referrer" content="no-referrer">
②、在图片img标签加入 referrerpolicy="no-referrer" 属性,大概意思是该图片的引用的时候,不发送Referer头信息(目前来看,只有ie浏览器不支持这种方式,其他浏览器都支持,不过我也没有想过要兼容ie)。
因为网站的编辑器默认是不会给图片加入 referrerpolicy="no-referrer" 参数的,所以需要通过前端(JavaScript)来处理,我目前是用jQuery来处理这个效果。
$(document).ready(function(){ //给文章内容区域的img标签增加 referrerpolicy="no-referrer" 参数,实现不发送Referer头部,达到绕过防盗链的效果 $('.main section .articletext img').attr('referrerpolicy', 'no-referrer'); });
后面发现,参数是加入进来了,但是图片没有变化,主要原因是图片参数是在网站图片加载完成过后,再通过JavaScript增加的,所以没有重新获取图片,要解决这个问题,可以给图片的路径增加随机参数,达到重新获取图片的效果。
$(document).ready(function(){ //给文章内容区域的img标签增加 referrerpolicy="no-referrer" 参数,实现不发送Referer头部,达到绕过防盗链的效果 $('.main section .articletext img').each(function(){ //设置referrerpolicy属性 $(this).attr('referrerpolicy', 'no-referrer'); //获取原始src var originalSrc = $(this).attr('src'); //在src后添加随机数强制重新加载 $(this).attr('src', originalSrc + '?' + new Date().getTime()); }); });
到这里,图片加载的问题解决了,但是又出现了新的问题,因为网站的文章图片,并不全是微信公众号的外链图片,如果所有的图片都加载两次(先默认加载,然后增加了 referrerpolicy="no-referrer" 参数再加载一次),就会增加服务器的资源和带宽消耗,所以,我只需要微信公众号过来的图片进行参数处理,其他的不变就可以了。
$(document).ready(function(){ //给文章内容区域的img标签增加 referrerpolicy="no-referrer" 参数,实现不发送Referer头部,达到绕过防盗链的效果 $('.main section .articletext img').each(function(){ //先判断是不是来自于微信公众号的图片服务器的域名,如果是就增加参数并更新图片,如果不是就维持现状 var imgSrc = $(this).attr('src'); var url = new URL(imgSrc); if (url.hostname === 'mmbiz.qpic.cn') { $(this).attr('referrerpolicy', 'no-referrer'); $(this).attr('src', imgSrc + '?' + new Date().getTime()); } }); });
自此,问题解决。
评论0