###背景 为了防止裸奔的静态图片和相关的附件被用户拿来随意拼装下载,需要研究特定的用户对特定资源的授权访问方案。当前为了满足大量用户的访问,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.PL
require 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版本的可以参考这个传送门 这个代码略有点乱。 ####在需要权限验证的地方加上密码
<img src="//myimg.com/images/1.jpg?token={{rsToken('/images/1.jpg')}}">