###背景 为了防止裸奔的静态图片和相关的附件被用户拿来随意拼装下载,需要研究特定的用户对特定资源的授权访问方案。当前为了满足大量用户的访问,web服务一般都有专用的静态资源服务器,逻辑服务器和静态资源服务域名不同、服务分开。进化高一些的大型站点,还有独立的验证服务。
###整体的架构方案 逻辑服务或者验证服务可以对每个静态资源计算一个特定的密码,访问静态资源时可以携带上这个密码,静态资源服务器在收到资源访问请求时先去解析密码,密码里有对资源路径的解密验证。
###静态资源服务器 采用nginx perl模块的方式进行验证。 ####nginx模块的编译
yum install -y perl-ExtUtils-Embed openssl-devel openssl-static openssl libtool-ltdl libtool-ltdl-devel./configure --prefix=/usr/local/web/nginx-1.6.2 --with-http_ssl_module --with-http_perl_module
需要自己安装libmcrypt(这个玩意太危险了,看起来已经很久维护了,这玩意能藏后门,fuck)
[root@localhost Mcrypt-2.5.7.0]# vim Makefile.PLrequire 5.004 ; use ExtUtils::MakeMaker 5.16 ; use Config ;$MCRYPT_LDFLAGS = "-L/usr/local/libmcrypt-2.5.7/lib" ; $MCRYPT_CPPFLAGS = "-I/usr/local/libmcrypt-2.5.7/include" ; WriteMakefile( NAME => 'Mcrypt', VERSION_FROM => 'Mcrypt.pm', LIBS => [ "$MCRYPT_LDFLAGS -lltdl -lmcrypt" ], INC => " $MCRYPT_CPPFLAGS" , );
####nginx的配置
perl_modules lib; perl_require proxy.pm; perl_set $auth ' sub { my $r = shift; return proxy::check($r); } '; server { listen 80; server_name myimg.com; root /root/web/blog/public; index index.html; if ($auth = 0) { return 400; } access_log logs/access_log combined; }
####proxy模块代理
package proxy;use strict;use DES;use nginx;sub check { my $r = shift; my $uri = $r->uri; my @uri_args = split(/&/, $r->args); my $auth_key = ""; my $flag = 0; foreach my $tmp (@uri_args) { $tmp=~s/^ +//; $tmp=~s/ +$//; my ($key, $value) = split(/=/, $tmp); if ($key eq "token") { $flag = 1; $auth_key = $value; last; } } if ($flag == 1) { return auth($auth_key, $uri); } else { return 0; }}sub auth { my $ticket = shift; my $ino = shift; my $mode = shift || 'cfb'; return () unless defined $ticket; my $salt = 'your password'; my $td = new DES(key=>$salt, mode=>$mode); my $data = $td->demcrypt($ticket); if ($data eq $ino) { return 1; } else { return 0; }}1;__END__
####加密和解密的方式 加密方式和解密方式可以跟据自己的情况自行选择,写到DES.pm中,里面只要有demcrypt和enmcrypt方法就好了。算法你可以去追求性能,或者追求安全的,或者你他娘的自己造也行。 如果你使用laravel框架,这里可以直接使用自带的 ####静态资源密码生成方式
function rsToken($uri_path){ $salt = 'Yc1+04ox'; $td = new DesService($salt); return $td->encrypt($uri_path);}
DES的加密和解密php版本的可以参考这个 这个代码略有点乱。 ####在需要权限验证的地方加上密码