使用nginx作图片服务器的访问权限控制

说到访问权限控制,很多看了nginx相关文章的朋友都会自然联想到X-Accel-Redirect这个头。这个头有个缺陷,就是所有的访问都会先经过一个fastcgi来判断权限。在下载系统上,用这个方法是非常合适的,但是在访问量非常大的图片服务器,单单用这个方法会使大量无需权限判定的图片也经过一个fastcgi处理,多此一举并且无端耗费大量的资源。虽然X-Accel-Redirect是一个新的方案,但是并不代表它能很好的解决所有问题,同时也不妨碍继续思考解决问题的其它办法。

图片服务器加上权限判断主要用于博客和相册这样的系统。在网上稍微观察,可以看到目前大部分的博客相册等系统并没有针对图片本身加入权限判断,而仅仅是将网页部分的权限控制住。这样的话很多网友将其图片加锁,实际上此图片在外部仍有办法打开。我估计此原因有其一是实现起来有性能问题,其二是诸多网站将图片放置到CDN上,而CDN并没有对此有相应的方案的缘故。走了一圈发现只有QQ空间在用带权限的图片,而它看上去是直接用fastcgi实现的,性能居然还不错,佩服一下。

下文单纯解决性能问题,其思路是在访问图片附近放置一个控制文件,通过nginx判断决定是否要到fastcgi认证,其原理类似apache的.htaccess。有用到CDN的,因为CDN多数是squid,要加入清理squid缓存的机制。

1、针对单一图片的控制

如果图片按照哈希结构放置,那么用户的图片加锁后要把每一张图片都加上控制文件,如果该用户图片较多,写入时稍嫌多些。

比如有一张图:

/data/image/a/z/asdfqerqwegasd.jpg

写上一个空文件:

/data/image/a/z/asdfqerqwegasd.jpg.lock

然后在nginx配置判断:

location / {
root /data/image/;
if ( -f “${request_filename}.lock” )
{
#rewrite ^(.*)$ http://www.sudone.com/access.jsp?url=$1 last;
return 403;#test
}
}

这样,只要在图片旁边有一个.lock文件,就会访问到403 Forbidden;使用rewrite会将图片链接和cookie定位到后端,由后端返回判定结果X-Accel-Redirect头或者重定向到另外一个jsp去填密码。

2、针对目录的控制

如果图片是按照目录放置,那么配置会稍微复杂一些。

location / {
root /data/image/;
if ( $request_filename ~ ^(.*)/[^/]*$ ){
set $dir $1;
}
if ( -f “${dir}/lock” )
{
#rewrite ^(.*)$ http://www.sudone.com/access.jsp?url=$1 last;
return 403;#test
}
}

首先用正则表达式取出图片路径的目录,然后带上控制文件名判断此文件是否存在,这样只要在图片的目录中放置一个名叫lock的空文件就能控制完整个目录:

/data/image/a/z/lock

测试一下,效果不错,只要控制文件存在,访问立刻403;删去控制文件,访问正常。

发表评论