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

omjgkv6w  于 2023-01-14  发布在  其他
关注(0)|答案(5)|浏览(143)

我已经安装了Laravel 5. 0,并进行了身份验证。一切正常。
我的网站只对认证会员开放。网站内容只对认证会员开放,但网站图片不对公众开放。
任何一个直接写图像URL的人都可以看到该图像,即使该人没有登录到系统。

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

**我的问题:**是否有可能保护图像(上面的URL示例)从公共视图,换句话说,如果图像的URL发送给任何人,个人必须是成员和登录才能看到图像。

这可能吗?怎么可能?

6ss1mwsb

6ss1mwsb1#

可以在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引入了新的更好的方式来服务文件,具有更少的开销(这种方式不会重新生成文件,如答案中所述):

文件响应

file方法可用于直接在用户的浏览器中显示文件(如图像或PDF),而无需启动下载。此方法接受文件路径作为其第一个参数,接受标题数组作为其第二个参数:

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

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

您可以修改您的存储路径和文件/文件夹结构,因为您希望适合您的要求,这只是为了演示我是如何做的,它是如何工作的。
您还可以添加条件以仅显示控制器中特定成员的图像。
此外,还可以使用文件名、时间戳和其他变量对文件名进行散列。

**补充:**有些人问此方法是否可以用作公共文件夹上载的替代方法,是的,可以,但不推荐此答案中解释的做法。因此,相同的方法也可以用于上载存储路径中的图像,即使您不打算保护它们,只需遵循相同的过程,但删除'middleware' => 'auth',。这样,您就不会在公共文件夹中给予777权限,仍然有一个安全的上载环境。上述相同的答案还解释了如何使用此方法,而不进行身份验证,以防有人使用它或提供替代解决方案。

enyaitl3

enyaitl32#

在以前的项目中,我通过以下操作保护了上传:
已创建存储磁盘

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

qni6mghb3#

我实际上还没有尝试过这个,但我发现Nginx auth_request模块允许您检查来自Laravel的身份验证,但仍然使用Nginx发送文件。
它发送一个内部请求到给定的url,并检查http代码是否成功(2xx)或失败(4xx),如果成功,则允许用户下载文件。
编辑:另一个选项是我尝试过的,看起来效果不错。你可以使用X-Accel-Redirect-header从Nginx提供文件。请求通过PHP,但不是发送整个文件,它只是将文件位置发送到Nginx,然后将其提供给客户端。

83qze16e

83qze16e4#

如果我理解你的话就像!

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

yxyvkwin5#

公用文件夹中的每个文件都可以在浏览器中访问。任何人只要找到文件名和存储路径就可以轻松获取该文件。
因此,更好的选择是将文件存储在公共文件夹之外,例如:/storage/app/private
现在执行以下步骤:
1.创建路由(例如:专用/{文件名})
路径::get(“/private/{文件名}”,[应用\Http\控制器\文件控制器::类,“视图”])-〉中间件([“授权”])-〉名称(“视图.文件”);
1.在控制器中创建返回文件路径的函数。要创建控制器,请运行命令php artisan make:controller FileController
并将视图函数粘贴到FileController中

public function view($file)
    {
        $filePath = "notes/{$file}";
        
        if(Storage::exists($filePath)){
            return Storage::response($filePath);
        }
        abort(404);
    }

然后,将use Illuminate\Support\Facades\Storage;粘贴到FileController for Storage中
1.不要忘记根据您的要求分配中间件(在路由器或控制器中)(例如:授权)
现在,只有有权访问该中间件的用户才能通过名为view.file的路由访问该文件

相关问题