PHP防盗链思路

闲来无事,突然想到用PHP做防盗链应该怎么做,目前我只知道可以通过web服务器(如nginx)通过请求header中的referer来判断
如果用PHP应该怎么做呢?

思路:

  • 所有文件资源访问路径都是由服务端返回,前端基于此来访问文件,因此,文件的所有访问由服务端控制
  • 服务端返回文件名称时可以给文件路径加密(注意此加密是可逆的),例如自定义一个key + 真实文件名进行加密
  • 服务端接收到加密的文件访问时通过给定的key进行解密,获得真实的文件名,然后服务器端直接输出文件流

以图片文件为例

<?php
//接收请求参数
$param = $_GET['u'];

//这一步是将文件路径名称和key加密 然后给客户端(我这里的key 是时间戳 每个整分变换一次)
//为例方便演示我这里的加密用的是base64
/*$date = date('Y-m-d H:00');
$pk = strtotime($date).'-lnmp.gif';
$name = 'lnmp.gif';
$img = base64_encode($pk);
*/

list($key,$img) = explode('-', base64_decode($param));
//TODO 获取到key以后可以和时间戳对比

if(!is_file($img)) {
    echo '文件资源不存在';die;
}
//获取文件信息
$info = getimagesize($img);
//获取文件后缀
$imgExt = image_type_to_extension($info[2], false);
$fun = "imagecreatefrom{$imgExt}";
$imgInfo = $fun($img);
//获取图片的 MIME 类型
$mime = image_type_to_mime_type(exif_imagetype($img));
//指定响应的Content-Type 这一步很重要,否则不能输出文件对应的type
header('Content-Type:'.$mime);
$quality = 100;
if($imgExt == 'png') $quality = 9;        //输出质量,JPEG格式(0-100),PNG格式(0-9)
$getImgInfo = "image{$imgExt}";
$getImgInfo($imgInfo, null, $quality);    //2.将图像输出到浏览器或文件。如: imagepng ( resource $image )
//直接输出
echo imagedestroy($imgInfo);

访问正常的文件路径,暴漏了真实的文件路径
1.png

访问加密后的文件,文件真实路径未知
2.png
访问错误的文件,提示错误
3.png

其它

  • key建议用时间戳
  • 设定间隔时间,每次生成新的加密路径给客户端
  • 同时访问资源时验证时间戳是否超过设定间隔时间
  • 由于时间戳变化,每次加密后的文件路径不同,旧有的访问必定失效

添加新评论