天天看点

文件安全之只允许网站内打开,禁止单独打开下载

有时候我们并不想一个网站文件,禁止单独打开,

举例:ios潮汐的音频文件,按道理都是收费的,肯定禁止别人通过某些手段获取到文件,但是潮汐目前大部分都能在web里面抓包抓取到,并且提取出来

这么防止这种数据安全呢?今天就拿我唯一玩的比较熟悉的语言php做一个demo释放:

1:首先,我们就拿laravel框架举例,例如我在 我在项目app文件夹下新建了一个文件default_thumb

文件安全之只允许网站内打开,禁止单独打开下载

2:在nginx里面配置路由重点  internal;

location /default_thumb {
	        root   D:/phpstudy_pro/WWW/bamboo/app;
	        add_header  Content-Type 'image/png';
            #下面可以先注释,直接浏览器打开default_thumb文件夹下一站图片尝试,是否可以打开,可以打开后在去掉前面的#号
	       	#internal;
	    }
           

 3:例如我们/default_thum文件夹下面有一个containers文件夹,下面有1_demo.jpg的图片一张

假设当前网站url访问路径是dd.com,那么浏览器访问:http://dd.com/default_thumb/containers/1_demo.jpg 

文件安全之只允许网站内打开,禁止单独打开下载
文件安全之只允许网站内打开,禁止单独打开下载

4:如果访问能成功,这里就可以把nginx里面的internal;前面#去掉

5:重启nginx,在访问是不文件已经不能访问了,这就需要代码解决了访问问题了

6:在项目新建一个控制器,新建一个方法:例如新建了image控制器,preview方法,参考代码如下

class ImageController extends Controller
{

    /**
     * 获取图片
     * @param string $path
     * @return JsonResponse
     * @date 2020/12/17 19:38
     */
    public function preview($path = '')
    {

        $path = base64_decode($path);
        if (empty($path)) {
            return $this->formatReturn([
                'state' => false,
                'error' => '图片路径为空'
            ]);
        }
        $imagesPath = explode('/', $path);
        //便于windows和linux系统转义符问题 linux可去掉
        $path = implode(DIRECTORY_SEPARATOR, $imagesPath);
        //app_path()方法注解  app('path').($path ? DIRECTORY_SEPARATOR.$path : $path);
        $src = app_path('default_thumb' . DIRECTORY_SEPARATOR) . $path;
        $delimiter = DIRECTORY_SEPARATOR . 'default_thumb' . DIRECTORY_SEPARATOR;
        if (!file_exists($src)) {
            return $this->formatReturn([
                'state' => false,
                'error' => '对应图片不存在'
            ]);
        }



        $filename = end($imagesPath);
        $ext=explode('.', $filename);
        $fileExt = end($ext);



        $mimeTypeArr = array(
            'png' => 'image/png',
            'gif' => 'image/gif',
            'jpg' => 'image/jpeg',
            'jpeg' => 'image/jpeg',
        );

        $mimeType = isset($mimeTypeArr[$fileExt]) ? $mimeTypeArr[$fileExt] : 'image/jpeg';
        //便于windows和linux系统转义符问题在转换回来 linux可去掉
        $path=$delimiter.$path;
        $filepath = implode('/', explode(DIRECTORY_SEPARATOR, $path));


        // 下载
        //header("Content-Disposition: attachment; filename= '{$filename}'");
        // 内嵌
        header("Content-Disposition: inline; filename= '{$filename}'");

        header("Content-Type:" . $mimeType);

        header('X-Accel-Redirect:' . $filepath);

        header("X-Accel-Buffering: yes");
        header("X-Accel-Limit-Rate :102400"); //速度限制 Byte/s

    }


    public function formatReturn(array $params, $cookie = '')
    {
        if (!isset($params['code'])) {
            $params['code'] = '';
        }
        if (isset($params['error']) && strpos($params['error'], 'SQLSTATE')) {
            if (env('APP_ENV') != 'local') {
                $params['error'] = '数据库查询有误';
            }
        }
        if (empty($cookie)) {
            return response()->json($params);
        } else {
            return response()->json($params)->cookie($cookie);
        }
    }
           

7:有了控制器和方法,在配置路由,就假设在 在web.php里面新加路由

Route::get('image/{path?}', "[email protected]");
           

8:做好了这些,看到路由后面只能接收一个参数,而且加上nginx配置了/default_thumb  所以访问http://dd.com/default_thumb/containers/1_demo.jpg 

需要把containers/1_demo.jpg 这个去解析成一个字符串,控制器方法里面是base64的,这里我们就拿到https://base64.us/,里面去编码一下,

结果就成了Y29udGFpbmVycy8xX2RlbW8uanBn

10:浏览器按照路由输入:https://dd.com/image/Y29udGFpbmVycy8xX2RlbW8uanBn 结果如下图,到这里就结束了,记住nginx里面internal;很重要

文件安全之只允许网站内打开,禁止单独打开下载