如何在 Laravel 5 中保护图像不被公众看到?

Posted

技术标签:

【中文标题】如何在 Laravel 5 中保护图像不被公众看到?【英文标题】:How to protect image from public view in Laravel 5? 【发布时间】:2015-08-21 08:12:35 【问题描述】:

我已经安装了 Laravel 5.0 并进行了身份验证。一切正常。

我的网站只对经过身份验证的会员开放。里面的内容只对经过身份验证的成员提供保护,但网站内部的图像不受保护以供公众查看。

任何人直接写入图片URL都可以看到图片,即使该人没有登录系统。

http://www.somedomainname.net/images/users/userImage.jpg

我的问题:是否可以保护图像(上面的 URL 示例)不被公众看到,换句话说,如果图像的 URL 发送给任何人,个人必须是会员并登录能够看到图像。

这可能吗?如何实现?

【问题讨论】:

你试过设置路由保护图片路径吗? 不,但我会尝试以下答案并让您知道 @haakym,下面的例子对我有用。你是对的,它在路上。 【参考方案1】:

如果我理解你,就像!

 Route::post('/download/id', function(Request $request , $id)
  

     if(\Auth::user()->id == $id) 
         return \Storage::download($request->f);
      
     else 
         \Session::flash('error' , 'Access  deny');
         return back();
     
  

 )->name('download')->middleware('auth:owner,admin,web');

【讨论】:

【参考方案2】:

可以在 Laravel 5.x 文件夹中保护图像免受公共视图的影响。

在 Laravel 中的 storage 文件夹下创建 images 文件夹(我选择了 storage 文件夹,因为它已经具有写入权限,当我将图像上传到它时可以使用它)喜欢storage/app/images

将要保护的图像从公用文件夹移动到新创建的images 文件夹。您也可以选择其他位置来创建 images 文件夹,但不在公用文件夹内,而是在 Laravel 文件夹结构中,但仍然是不在控制器文件夹内的逻辑位置示例。接下来你需要创建一个路由和图像控制器。

创建路线

Route::get('images/users/user_id/slug', [
     'as'         => 'images.show',
     'uses'       => 'ImagesController@show',
     'middleware' => 'auth',
]);

如果人未登录,该路由会将所有图像请求访问转发到身份验证页面。

创建图像控制器

class ImagesController extends Controller 

    public function show($user_id, $slug)
    
        $storagePath = storage_path('app/images/users/' . $user_id . '/' . $slug);
        return Image::make($storagePath)->response();
    


编辑(注意)

适用于使用 Laravel 5.2 及更新版本的用户。 Laravel 为 serve files 引入了新的更好的方法,它的开销更少(这种方法不会像答案中提到的那样重新生成文件):

文件回复

file 方法可用于显示文件,例如图像或 PDF,直接在用户的浏览器中,而不是启动下载。 这个方法接受文件的路径作为它的第一个参数和一个 标头数组作为其第二个参数:

return response()->file($pathToFile);

return response()->file($pathToFile, $headers);

您可以根据需要修改存储路径和文件/文件夹结构,这只是为了演示我是如何做到的以及它是如何工作的。

您还可以添加条件以仅显示控制器中特定成员的图像。

另外还可以用文件名、时间戳等变量对文件名进行哈希处理。


补充: 有人问此方法是否可以用作公用文件夹上传的替代方法,可以,但不建议这样做,如answer 中所述。因此,即使您不打算保护它们,也可以使用相同的方法上传存储路径中的图像,只需按照相同的过程删除'middleware' => 'auth',。这样您就不会在公用文件夹中授予 777 权限,并且仍然拥有安全的上传环境。同样提到的answer 还解释了如何在没有身份验证的情况下使用这种方法,以防有人会使用它或提供替代解决方案。

【讨论】:

不建议在没有保护的情况下正常上传图片,因为性能会比让 apache\nginx 处理图片服务差很多 @AmirBar 您的替代解决方案是什么? 普通图片上传,不需要保护,然后上传到公共文件夹,让nginx处理 @AmirBar 仅当您需要它来保护您的文件并且是的我同意正常上传将在您的公用文件夹上时,但最后一点是因为有些人在另一个 cmet 中要求它从另一个问题,我添加了注释。 我假设上面的Image::make 方法来自intervention/image 包?【参考方案3】:

在之前的项目中,我通过执行以下操作来保护上传:

创建存储磁盘

config/filesystems.php
'myDisk' => [
        'driver' => 'local',
        'root' => storage_path('app/uploads'),
        'url' => env('APP_URL') . '/storage',
        'visibility' => 'private',
    ],

这会将文件上传到\storage\app\uploads\public 无法查看。

在控制器上保存文件:

Storage::disk('myDisk')->put('/ANY FOLDER NAME/' . $file, $data);

为了让用户查看文件并保护上传内容不被未经授权访问。首先检查磁盘上是否存在文件:

public function returnFile($file)

    //This method will look for the file and get it from drive
    $path = storage_path('app/uploads/ANY FOLDER NAME/' . $file);
    try 
        $file = File::get($path);
        $type = File::mimeType($path);
        $response = Response::make($file, 200);
        $response->header("Content-Type", $type);
        return $response;
     catch (FileNotFoundException $exception) 
        abort(404);
    

服务如果用户有正确的访问权限:

 public function licenceFileShow($file)

    /**
     *Make sure the @param $file has a dot
     * Then check if the user has Admin Role. If true serve else
     */
    if (strpos($file, '.') !== false) 
        if (Auth::user()->hasAnyRole(['Admin'])) 
            /** Serve the file for the Admin*/
            return $this->returnFile($file);
         else 
            /**Logic to check if the request is from file owner**/
            return $this->returnFile($file);
        
     else 
//Invalid file name given
        return redirect()->route('home');
    

终于在 Web.php 路线上:

Route::get('uploads/user-files/filename', 'MiscController@licenceFileShow');

【讨论】:

【参考方案4】:

我实际上并没有尝试过,但我发现 Nginx auth_request 模块允许您检查来自 Laravel 的身份验证,但仍然使用 Nginx 发送文件。

它向给定的 url 发送一个内部请求,并检查 http 代码是否成功(2xx)或失败(4xx),成功后,让用户下载文件。

编辑:另一个选项是我尝试过的,它似乎工作正常。您可以使用 X-Accel-Redirect -header 从 Nginx 提供文件。请求通过 PHP,但不是通过发送整个文件,它只是将文件位置发送到 Nginx,然后将其提供给客户端。

【讨论】:

以上是关于如何在 Laravel 5 中保护图像不被公众看到?的主要内容,如果未能解决你的问题,请参考以下文章

如何保护 swf 文件不被查看?

如何保护 azure blob 存储 url 不被任何使用开发人员工具的人检索

如何保护视频不被下载 Vimeo [关闭]

iOS Swift4如何保护接口中定义的计算属性不被赋值?

javascript 保护内容不被复制文本,拖动图像,查看源和禁用具有图像路径的链接。

保护 Web api 不被浏览器外部调用