如何在Laravel 5中保护图像免受公众视线影响?

时间:2015-06-06 11:42:53

标签: laravel laravel-5 laravel-5.2 laravel-5.1 laravel-5.3

我安装了Laravel 5.0并进行了身份验证。一切都很好。

我的网站仅对经过身份验证的成员开放。内部内容仅受Authenticated成员保护,但站点内的图像不受公共视图保护。

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

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

我的问题:是否可以从公共视图保护图片(上面的网址示例),在其他Word中如果图片的网址发送给任何人,则该个人必须是会员并登录能够看到图像。

这可能吗?如何?

4 个答案:

答案 0 :(得分:26)

可以在Laravel 5.x文件夹中保护公开视图中的图像。

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

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

创建路线

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

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

创建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();
    }
}

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

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

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

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

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:1)

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

创建的存储磁盘

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

这会将文件上传到\storage\app\uploads\公开无法使用。

要在控制器上保存文件,

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

答案 3 :(得分:0)

如果我能理解你,就像!

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