阿权今天要说的问题是:
用户粘贴的图片是对方防盗链处理的图片,别人就无法看到图片了,体验很不好。

有问题就有解决办法,但需要预热一下:
1 别人是如何做图片防盗链的?
2 如何可以避免在防盗链范围?

了解或者解决以上两个问题你就可以出师了啦!

众所周知,图片防盗链是为了让自己的服务器提供给固定的某些域名下的网页显示自己的图片,主要为了解决带宽的占用问题。
阿权之前管理的图片类型的网站,居然可以让盗链的图片流量跑满了服务器带宽,所以盗链的问题很讨厌,一般网站都会处理此问题,一般采取的是检查图片请求的referer参数,这个不明白那这个课题还不适合你来读。

我们来看看凤凰网的图片防盗链,图片是很hot的美女哦,curl就可以测试:

[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg
HTTP/1.1 200 OK
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:14:31 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Wed, 10 Jun 2009 11:16:05 GMT
Accept-Ranges: bytes
Content-Length: 37727
Expires: Wed, 23 Jun 2010 08:11:48 GMT
Cache-Control: max-age=31536000
X-Cache: HIT from cache26.ifeng.com
Age: 24507
X-Cache: HIT from CNC-BJBY-53-172.fastcdn.com

[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg -H "referer:http://www.aslibra.com/"
HTTP/1.1 403 Forbidden
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:14:57 GMT
Content-Type: text/html
Connection: keep-alive
Content-Length: 1204
Expires: Fri, 26 Jun 2009 13:15:02 GMT
X-Squid-Error: ERR_ACCESS_DENIED 0
X-Cache: MISS from CNC-BJBY-53-172.fastcdn.com

[root@aslibra ~]# curl -I http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg -H "referer:http://img.ifeng.com/"
HTTP/1.1 200 OK
Server: DnionOS/1.0
Date: Fri, 26 Jun 2009 13:17:37 GMT
Content-Type: image/jpeg
Connection: keep-alive
Last-Modified: Wed, 10 Jun 2009 11:16:05 GMT
Accept-Ranges: bytes
Content-Length: 37727
Expires: Wed, 23 Jun 2010 08:11:48 GMT
Cache-Control: max-age=31536000
X-Cache: HIT from cache26.ifeng.com
Age: 24691
X-Cache: HIT from CNC-BJBY-53-172.fastcdn.com


第一个是没有来源标识的,一般为在窗口直接输入图片地址
第二个是模拟在网页里面的图片,网址假设为http://www.aslibra.com/
第三个是模拟在img.ifeng.com的网页打开的

第一个和第三个返回是200的状态码,图片正常,第二个则因为是非授权网页引用,返回了403禁止的消息。
也有可能是返回200的状态码的,比如百度hi的图片:

[root@aslibra ~]# curl -I http://hiphotos.baidu.com/yuanyingmanhua/pic/item/6e1da9d832163a3b33fa1c2b.jpg
HTTP/1.1 200 OK
...
Cache-Control: max-age=315360000
Expires: Sun, 08 May 2016 14:12:03 GMT
Last-Modified: Sat, 29 Apr 2006 07:04:00 GMT
Content-Length: 43171
...

[root@aslibra ~]# curl -I http://hiphotos.baidu.com/yuanyingmanhua/pic/item/6e1da9d832163a3b33fa1c2b.jpg -H "referer:http://www.aslibra.com/"
HTTP/1.1 200 OK
...
Cache-Control: no-cache
Content-Length: 1809
...


当然,如果对方服务器是验证用户的信息的,那就没法解决了,我们能够解决的防盗链一般是根据来源防盗链的服务器。
注意了,破解对方的防盗链并非坏事,是为了提高用户体验,解决一般的用户的疑惑,他们根本不知道粘贴的图片为什么不正常,这你没必要跟他们聊一下图片防盗链吧?

你也许只要付出一台服务器就可以解决了:
1 首先你得把防盗链的域名的图片地址给替换为你的服务器域名,因为正常的访问你是控制不了referer信息的
2 交给代理服务器去掉或者修改referer信息,这个nginx很简便解决
3 再交给缓存服务器下载此图片,缓存此图片,这样对对方服务器没有什么影响,是好事来的

步骤1:替换图片地址

第一个就不用多说了,比如php就可以处理:

//example php code
$content = ereg_replace("http://($domain)/", "http://proxy.www.aslibra.com/m/\\1/", $content);
// from http://img.ifeng.com/res/200906/0610-070615_1339_20.jpg
// to http://proxy.www.aslibra.com/m/img.ifeng.com/res/200906/0610-070615_1339_20.jpg


这样的简单处理可以保留所有的图片地址信息,而且可以自动还原原来的请求地址

步骤2 去掉或更改referer信息

这个有很多方法,比如配置proxy.www.aslibra.com/m交给php处理,php容易分析出地址,并且可以用socket或者调用curl等系统命令来下载图片,然后返回给用户。
这里用web服务器(nginx)解决这个问题,肯定比php来的简便和高效:

upstream squid {
  server 127.0.0.1:3128;
}
server {
  expires       240h;
  server_name  proxy.www.aslibra.com;
  if ( $uri ~ ^/m/([^/]+)(.+)) {
    set $new_host $1;
    set $referer "";
    #set $referer http://$1/; #you can set it like this
    rewrite ^/m/([^/]+)(.+) $2 break;
  }
  location / {
    proxy_set_header host $new_host;
    proxy_set_header referer  $referer;
    proxy_pass        http://squid;
  }
}


简单来说就是rewrite回原先的地址,并且设置referer,交给squid的后端。

步骤3 交给代理服务器缓存

visible_hostname cache.aslibra.com
acl all src 0.0.0.0/0.0.0.0
http_access allow all
http_port 127.0.0.1:3128
httpd_accel_host virtual
httpd_accel_port 80
httpd_accel_uses_host_header on
httpd_accel_with_proxy off
cache_dir ufs /cache/proxy.www.aslibra.com 2000 16 256
cache_effective_user daemon
cache_access_log none
cache_store_log none
cache_log none


以上是squid的配置(2.5版本),基本不用配置什么参数,能代理缓存即可,有别的合适软件也许也可以做,但squid做这个实在是太合适了!你的不二之选!

实验效果很正常,返回的信息如下,访问两次有HIT说明就正常了:

(Status-Line)  HTTP/1.1 200 OK
Cache-Control  max-age=864000
Connection  keep-alive
Content-Length  59969
Content-Type  image/jpeg
Date  Fri, 26 Jun 2009 13:42:32 GMT
Expires  Mon, 06 Jul 2009 13:42:32 GMT
Last-Modified  Mon, 18 Dec 2006 07:25:14 GMT
Server  nginx/0.7.59
X-Cache  HIT from cache.aslibra.com


点击在新窗口中浏览此图片

效果对比,前面会提示禁止引用,后面是解决后正常显示图片的效果!
很神奇吧~~ 这样就为用户体验提高了一个等级啦~
注意,以上方案域名为测试指定,访问并非正常,请自行修改相关内容进行试验,大家使用愉快!

本方案更新请关注:
http://www.aslibra.com/blog/post/crack_pic_referer_solution.php

本解决方案目前无法解决的类型:

1 不是判断referer信息来防盗链的,当然如果你知道,也许可以类似方式解决
2 不能解决redirect后的图片,也许可以使用nginx的内部redirect来处理,还没试验,这类情况还不多



原创内容如转载请注明:来自 阿权的书房
收藏本文到网摘
Tags: , , ,
yea
2010/11/25 09:23
居然搜到你这里来了。最近闲紧,刚好想写段代码下载几百张照片。碰到防盗这个麻烦事。^-^
hqlulu 回复于 2010/11/25 11:28
可以参考。。 curl很强大的
韩国童装批发网 Homepage Email
2010/09/06 22:30
阿权真是有心人,有问必笿,呵呵,我又搜索回到此处,目前:韩衣8网站已经分拆成两台服务器,使用一台服务器作为专用图片服务器!访问速度大大的提升!!希望明年网站能做到需要3台服务器!!呵呵!!
hqlulu 回复于 2010/09/07 09:08
你也挺有心的
韩国童装批发 Homepage
2010/09/03 07:34
谢谢阿权的解答!呵呵,可笑的是我这边研究怎么盗用别人的图片,韩衣8韩国服装批发网确被别人在天天采集,网站是ECSHOP做的,目前商品量已经达到7万款,估计总量会在20万左右,不知道阿权对服务器技术有了解不?我自己是正在考虑将图片服务器独立出来,不知首阿权兄弟有什么好的方案能推荐一下的!
hqlulu 回复于 2010/09/03 10:12
这些基本的部署网上查一下就有,没什么说的
韩国童装批发 Homepage
2010/09/01 10:24
如果是用PHP来盗取图片,模拟的COOKIE是会过期的,而且我要盗的这个网站一个用户同时只能一个人登陆。有没有更好的解决方案?我的服务器是APACHE的!!这是我的小站:韩衣8韩国服装批发
hqlulu 回复于 2010/09/01 12:12
可以用curl模拟浏览器行为,自己做好cookie过期后重新登录的编程
leebird
2010/07/30 01:51
多谢楼主!后来加上cookie果然可以了。我在windows下用wireshark抓到的包还不完全,cookie的内容最后有一小段被截掉了,又弄了好久。
后来还遇到blogbus有一类链接不仅检查cookie,header里的许多域像user-agent, host都检查,反正要是只有cookie就不行。不过服务器环境变成了ngnix,之前的服务器环境是apache。不太清楚是什么原因。
再次感谢!
hqlulu 回复于 2010/07/30 09:01
不客气,你可以换个工具抓包试试,ie下的httpwatch,firefox下的httpfox
leebird
2010/07/29 21:57
我也在用curl下载blogbus的图片,可是遇到问题。
比如以下链接:
http://vfiles.blogbus.com/duckduckb.blogbus.com/files/11873375600.jpg
直接访问可以下载,我用curl下载到的却是一段奇怪的html提示,目前找不到原因。楼主可不可以帮忙看一下?多谢。
hqlulu 回复于 2010/07/29 23:01
对方有cookie验证:

$ curl -I -H "User-Agent:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; CIBA)" http://vfiles.blogbus.com/duckduckb.blogbus.com/files/11873375600.jpg
HTTP/1.1 302 Found
Date: Thu, 29 Jul 2010 14:56:34 GMT
Server: Apache
Location: http://www.blogbus.com/support/403.php
Cache-Control: max-age=31536000
Expires: Fri, 29 Jul 2011 14:56:34 GMT
Content-Type: text/html; charset=iso-8859-1

仿照IE访问的时候发送的cookie就可以了,比如:

$ curl -I -H "Cookie:__utma=42272954.787720732.1262596998.1280109617.1280415228.9; __utmz=42272954.1280415228.9.4.utmcsr=blogbus|utmccn=blog|utmcmd=404; __gads=ID=076d942528b865a6:T=1262597010:S=ALNI_MavjePOPioL66a8PeRde7lbEZC6gw; cmt_remember=no; valid=blogbus.com; __utmb=42272954.1.10.1280415228" http://vfiles.blogbus.com/duckduckb.blogbus.com/files/11873375600.jpg
HTTP/1.1 200 OK
Date: Thu, 29 Jul 2010 15:00:13 GMT
Server: Apache
Last-Modified: Fri, 17 Aug 2007 07:48:06 GMT
Accept-Ranges: bytes
Content-Length: 29236
Cache-Control: max-age=31536000
Expires: Fri, 29 Jul 2011 15:00:13 GMT
Node: F1G1H17
Content-Type: image/jpeg
squid
2009/11/07 17:40
还是不会用啊,发个傻瓜式的吧shuai
hqlulu 回复于 2009/11/07 22:33
能用就用吧,实在没有理解那就没办法了,也许你并不太需要这样的功能的
ben Homepage
2009/10/21 00:08
有点卡!能否尽可能细节的给出PHP源码呢?
谢谢~
hqlulu 回复于 2009/10/21 09:26
这个其实和php关系不太大,php(或者asp/jsp)只是做一个地址转换而已,主要是这个事情的思路
网友
2009/06/30 18:54
好东西,收藏了。用到在看看
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemotemotemotemotemotemotemotemotemot
emotemotemotemotemotemotemotemotemotemotemotemot
打开HTML 打开UBB 打开表情 隐藏
昵称   密码   游客无需密码
网址   电邮   [注册]
               

验证码 不区分大小写
 

阅读推荐

服务器相关推荐

开发相关推荐

应用软件推荐