解决微博图床防盗链无非有下面几种:
1、在
<meta name="referrer" content="no-referrer" />
这段代码简单易上手,直接在wordpress的主题文件找到header.php,在
中间加入上述代码,全站的图片立马恢复本来面目。但是,缺点很明显:从你网站引导到其他网站的流量不显示来路,对于挂广告的站点来说,风险极大,容易被联盟封号。而且不利于分析网站的营销能力。所以,只能做个备选项了。2、用nginx做反代。这个方法相对复杂,但是却最可靠,需要的小伙伴可以参考下面的代码自己部署:
<?php /** * 1.增加对gif的支持 * 2.对源图片的显示 * 3.非常强悍,哪怕url有跳转,也能正常显示最终的图片 * 4.gif不支持水印,其他格式没问题 * 5.支持https了 * 6.对有错的、不存在的图片,进行友好的提示 */ class ImgBridge{ private $water=''; private $imgUrl=''; private $referer=''; private $ua='MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1'; private $imgCode=''; private $imgHeader=''; private $imgBody=''; private $imgType=''; public function __construct($config=array()){ foreach($config as $key=>$value){ $this->$key=$value; } } public function getImg($imgUrl){ $this->imgUrl=$imgUrl; /** 处理url */ if(substr($this->imgUrl,0,7)!=='http://' && substr($this->imgUrl,0,8)!=='https://'){ $this->imgUrl='http://'.$this->imgUrl; } /** 解析url中的host */ $url_array=parse_url($this->imgUrl); /** 设置referer */ $this->referer=$this->referer==""?'http://'.$url_array['host']:$this->referer; /**开始获取 */ $this->urlOpen(); $this->imgBody; /**处理错误 */ if($this->imgCode!=200){ $this->error(1); exit(); } /**获取图片格式 */ preg_match("/Content-Type: image\/(.+?)\n/sim",$this->imgHeader,$result); /**看看是不是图片 */ if(!isset($result[1])){ $this->error(2); exit(); }else{ $this->imgType=$result[1]; } /** 输出内容 */ $this->out(); } private function out(){ /** gif 不处理,直接出图 */ if($this->imgType=='gif'){ header("Content-Type: image/gif"); echo $this->imgBody; exit(); } header("Content-Type: image/png"); /** 其他类型的,加水印 */ $im=imagecreatefromstring($this->imgBody); $white = imagecolorallocate($im, 255, 255, 255); /*加上水印*/ if($this->water){ imagettftext($im, 12, 0, 20, 20, $white, "/fonts/hwxh.ttf", $this->water); } imagepng($im); } private function error($err){ header("Content-Type: image/jpeg"); $im=imagecreatefromstring(file_get_contents('./default.jpg')); imagejpeg($im); } private function urlOpen() { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $this->imgUrl); curl_setopt($ch, CURLOPT_USERAGENT, $this->ua); curl_setopt ($ch,CURLOPT_REFERER,$this->referer); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_HEADER, 1); /**跳转也要 */ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); /** 支持https */ $opt[CURLOPT_SSL_VERIFYHOST] = 2; $opt[CURLOPT_SSL_VERIFYPEER] = FALSE; curl_setopt_array($ch, $opt); $response = curl_exec($ch); $this->imgCode=curl_getinfo($ch, CURLINFO_HTTP_CODE) ; if ($this->imgCode == '200') { $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); $this->imgHeader = substr($response, 0, $headerSize); $this->imgBody = substr($response, $headerSize); return ; } curl_close($ch); } } $img=new ImgBridge(array('water'=>'')); $img->getImg(strstr($_SERVER["QUERY_STRING"], "http"));
代码命名为img-reverse-proxy.php
那么直接可以访问
http://你的域名/img-reverse-proxy.php?url=防盗链图片地址
不过这样做有个缺陷就是所有的图片跑的都是你自己服务器的带宽(等于是你在给远程图片做CDN加速),虽然图片不在本地,不占磁盘空间,但是配置比较低的小鸡带宽可能吃不消。
3、修改微博图床生成的图片的服务器地址。比如,新浪几个常用的:wx1.sinaimg.cn,wx2.sinaimg.com,ws2.sinaimg.cn等,直接修改为:tva1.sinaimg.cn。这个方法现在还可以正常使用。但不知道能挺多久。
4、这其实是第1种方法的变种。将“no-referrer”标签直接添加到文章中微博图片的img标签里。具体代码如下:
/** Auto-Generate referrerpolicy="no-referrer" to images **/ /** 解决新浪微博图床防盗链**/ function image_referrerpolicy_tag($content){ global $post;preg_match_all('/<img(.*?)sinaimg(.*?)\/>/', $content, $images); if(!is_null($images)) {foreach($images[1] as $index => $value) { $new_img = str_replace('<img', '<img referrerpolicy="no-referrer"', $images[0][$index]); $content = str_replace($images[0][$index], $new_img, $content);}} return $content; } add_filter('the_content', 'image_referrerpolicy_tag', 99999);
这段代码的作用是:正则查找文章中有出现*.sinaimg.cn的图片,将【img】替换成【img referrerpolicy=”no-referrer”】。而如果不是微博图床的图片,则不需要替换。这样就堪称完美了。
文章前台查看源代码,会出现如下:
这样做还是有一定的缺陷:那就是部分老旧的浏览器,不支持这个referrerpolicy标签。不过受影响应该不是不大。算是我认为目前最完美的方法了。至于为什么不换其他图床,一方面是要钱,一方面是微博图床的打开速度确实给力!
补充一点:上述代码只是解决了前台新浪图床的图片显示的问题,如果在后台编辑器里面你也希望显示新浪图片的话,你还需要在functions.php里添加如下代码:
// 添加referrer标签 //add_action('wp_head', 'zm_admin_referrer');// 前端显示新浪图片(这一句可加可不加,加上后跟上面的第4点代码有冲突,二选一吧) add_action('admin_head', 'zm_admin_referrer');// 后台也显示新浪图片 add_action('login_head', 'zm_admin_referrer');// 登录注册页面也显示新浪图片 function zm_admin_referrer(){ echo'<meta name="referrer" content="no-referrer" />'; }
有的主题在文章详情页添加了相关文章(related articals)的推荐,如果新浪图片不显示的话,还可以直接到主题文件夹的下single.php里找到该图片调用的地方,在img标签里加上 referrerpolicy=”no-referrer”即可。