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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30682421/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 11:43:31  来源:igfitidea点击:

How to protect image from public view in Laravel 5?

laravellaravel-5laravel-5.2laravel-5.1laravel-5.3

提问by maytham-???????

I have installed Laravel 5.0 and have made Authentication. Everything is working just fine.

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

My web site is only open for Authenticated members. The content inside is protected to Authenticated members only, but the images inside the site is not protected for public view.

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

Any one writes the image URL directly can see the image, even if the person is not logged in to the system.

任何人直接写图片网址都可以看到图片,即使这个人没有登录系统。

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

My Question:is it possible to protect images (the above URL example) from public view, in other Word if a URL of the image send to any person, the individual must be member and login to be able to see the image.

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

Is that possible and how?

这是可能的吗?

回答by maytham-???????

It is possible to protect images from public viewin Laravel 5.x folder.

可以在 Laravel 5.x 文件夹中保护图像不被公开查看

  • Create imagesfolder under storagefolder (I have chosen storagefolder because it has write permission already that I can use when I upload images to it) in Laravel like storage/app/images.

  • Move the images you want to protect from public folder to the new created imagesfolder. You could also chose other location to create imagesfolder but not inside the public folder, but with in Laravel folder structure but still a logical location example not inside controller folder. Next you need to create a route and image controller.

  • 在 Laravel 中的images文件夹下创建文件storage夹(我选择了storage文件夹,因为它已经具有写入权限,我可以在向其上传图像时使用),例如storage/app/images.

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

Create Route

创建路线

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

The route will forward all image request access to Authentication page if person is not logged in.

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

Create ImagesController

创建图像控制器

class ImagesController extends Controller {

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



EDIT (NOTE)编辑(注意)

For those who use Laravel 5.2 and newer. Laravel introduces new and better way to serve filesthat has less overhead (This way does not regenerate the file as mentioned in the answer):

对于那些使用 Laravel 5.2 及更新版本的人。Laravel 引入了新的更好的方式来提供更少开销的文件(这种方式不会像答案中提到的那样重新生成文件):

File Responses

The file method can be used to display a file, such as an image or PDF, directly in the user's browser instead of initiating a download. This method accepts the path to the file as its first argument and an array of headers as its second argument:

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

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

文件响应

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

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

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


You can modify your storage path and file/folder structure as you wish to fit your requirement, this is just to demonstrate how I did it and how it works.

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

You can also added condition to show the images only for specific members in the controller.

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

It is also possible to hash the file name with file name, time stamp and other variables in addition.

此外,还可以使用文件名、时间戳和其他变量来散列文件名。



Addition:some asked if this method can be used as alternative to public folder upload, YES it is possible but it is not recommended practice as explained in this answer. So the same method can be also used to upload images in storage path even if you do not intend to protect them, just follow the same process but remove 'middleware' => 'auth',. That way you won't give 777 permission in your public folder and still have a safe uploading environment. The same mentioned answeralso explain how to use this method with out authentication in case some one would use it or giving alternative solution as well.

另外:有些人问此方法是否可以用作公用文件夹上传的替代方法,是的,这是可能的,但不建议按照此答案中的说明进行练习。因此,即使您不打算保护它们,也可以使用相同的方法将图像上传到存储路径中,只需按照相同的过程将'middleware' => 'auth',. 这样你就不会在你的公共文件夹中授予 777 权限,并且仍然有一个安全的上传环境。同样提到的答案还解释了如何在没有身份验证的情况下使用这种方法,以防有人使用它或提供替代解决方案。

回答by Dilaz

I haven't actually tried this but I found Nginx auth_requestmodule that allows you to check the authentication from Laravel, but still send the file using Nginx.

我还没有真正尝试过这个,但我发现 Nginxauth_request模块允许您检查来自 Laravel 的身份验证,但仍然使用 Nginx 发送文件。

It sends an internal request to given url and checks the http code for success (2xx) or failure (4xx) and on success, lets the user download the file.

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

Edit: Another option is something I've tried and it seemed to work fine. You can use X-Accel-Redirect-header to serve the file from Nginx. The request goes through PHP, but instead of sending the whole file through, it just sends the file location to Nginx which then serves it to the client.

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

回答by Abdelsalam Shahlol

In a previous project I protected the uploads by doing the following:

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

Created Storage Disk:

创建的存储磁盘

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

This will upload the files to \storage\app\uploads\which is not available to publicviewing.

这将上传公众\storage\app\uploads\无法查看的文件。

To save files on your controller:

要在控制器上保存文件:

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

In order for users to view the files and to protect the uploads from unauthorizedaccess. First check if the file existon the disk:

为了让用户查看文件并防止未经授权的访问上传。首先检查磁盘上是否存在该文件:

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);
    }
}

Servethe file if the user have the right access:

服务的文件,如果用户有权访问:

 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');
    }
}

Finally on Web.phproutes:

最后在Web.php路由上:

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

回答by Mohamed Amin

if I am understanding you it's like !

如果我理解你,就像!

 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');