一、下载功能其实很好实现,原来直接将文件的地址直接放在a里就可以实现了。但是这样给系统的安全性带来了不少的隐患。怎样隐藏下载文件的真实地址?
有一种办法,其主要思想是:1.以二进制数据流方式打开欲下载文件。2.按二进制数据流读取,并输出3.输出的内容强制浏览器打开一个下载框,以便下载。
打开一个文件可以用fopen()方法,文件的路径在此方法中以参数的方式传入,这样便实现了隐藏文件真实路径的目的,而不是简单的用a将文件绝对路径暴露。下面是我写的一个简单的下载类:(重要部分已添加说明)
class downLoad {
function downLoading( $fileUrl , $fileName ){
// 判断文件是否存在
if ( $this -> fileExists( $fileUrl , $fileName ) == false ){
exit ();
}
// 获得文件大小
$fileSize = filesize ( $fileUrl . $fileName );
// 已二进制方式打开文件
$objDownload = fopen ( $fileUrl . $fileName , " rb " );
// 发送header
header ( " Content-type:application/octet-stream " ); // 设置文件类型为二进制数据流
header ( " Content-length:$fileSize " ); // 文件大小
header ( " Content-Disposition: attachment;filename=$fileName " ); // 提供推荐的文件名来强制浏览器弹出一个保存文件对话框。
fpassthru ( $objDownload );
}
function fileExists( $fileUrl , $fileName ){
$what = file_exists ( $fileUrl . $fileName );
return $what ;
}
}
?>
二、虽然实现了文件路径的隐藏,但是还是感到不是十分的安全。
功能1、当该文件需注册后才能下载
if ( ! isset ( $_SESSION [ " loginname " ])){
echo " 对不起,你无权下载! " ;
exit ();
} else {
$do = new downLoad();
$do -> downLoading( " ../download/file " , $_GET [ " filename " ]);
}
功能2.每个用户有自己的下载文件,其他用户不能下载。
功能1可以简单的过滤下载用户,但是只要存在session在url中输入其他文件地址就可以下载其他用户的任意文件了,不好。
失败案例1:我试着禁掉用户在url中输入下载地址:(http_referer为链接到该页的前一页地址,server_name为当前运行脚本所在服务器主机的名称。当前一页中以a链接至此页时http_referer有值,而当使用页面刷新、header、javascript时http_referer不存在!这三种方式在IE中不会视为事件使http_referer产生值!)
$httpReferer = $_SERVER [ ' HTTP_REFERER ' ];
$requestArray = explode ( " / " , $httpReferer );
$requestSN = $requestArray [ 2 ];
if ( $httpReferer == "" || $requestSN != $serverName ){
echo " 非法链接! " ;
exit ();
}
这样只有在用户在本站中有<a href=""></a>链接时才能下载该文件,其他网站的盗用或着url直接输入不会下载该文件。(假设本站不会提供其他用户资源的a链接,只提供该用户自己的资源链接地址)用户在想要非法下载其他用户的资源时,一般会在url中输入地址,这样貌似解决了功能2的需求,但是当使用迅雷工具下载时,在其提供的url输入地址却任然可以下载其他用户资源,这是因为,当以迅雷下载时,可以看做触发了a时间http_referer不为空!
2.其他思想:
想用户下载资源似有化貌似只能使该用户id对应自己相应的资源。
方法1.存储一个用户下载列表。当下载时比对。
方法2.使用标志位来命名资源。当下载是判断。
方法3.使用linux中的权限控制。(未实现)
以上纯属个人看法,忘大虾务笑。下载安全问题一直是块心病,倘若有更好的方法,还忘高人指教。小弟谢过。