How can I recover an image from the Storage Folder without passing parameter in Route Laravel5.2?

0

How to recover an image of the Storage Folder without passing parameter in the Laravel Route?

My current code is working, but I'm having security problems because when I pass the parameter on the route the logged in user can see the image of another user by the URL if he knows the path.

Controller

 public function getAccount()
{
    return view('account', ['user' => Auth::user()]);
}

public function postSaveAccount(Request $request)
{
    $this->validate($request, [
       'email' => 'required|email|max:100'
    ]);

    $user           = Auth::user();
    $old_email      = $user->email;
    $user->email    = $request['email'];

    $user->update();
    $file = $request->file('image');

    $file_email     = $request['email'] . '-' . $user->id . '.jpg';
    $old_file_email = $old_email . '-' . $user->id . '.jpg';
    $update = false;

    if (Storage::disk('local')->has($old_file_email)) {
        $old_file = Storage::disk('local')->get($old_file_email);
        Storage::disk('local')->put($file_email, $old_file);
        $update = true;
    }

    if ($file) {
        Storage::disk('local')->put($file_email, File::get($file));
    }

    if ($update && $old_file_email !== $file_email) {
        Storage::delete($old_file_email);
    }
    return redirect()->route('account');
}

public function getUserImage($file_email)
{
    $file = Storage::disk('local')->get($file_email);
    return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);
}

Route

Route::get('/account', [
    'uses' => 'UserController@getAccount',
    'as'     => 'account'
]);

Route::post('/upateaccount', [
    'uses' => 'UserController@postSaveAccount',
    'as'     => 'account.save'
]);

Route::get('/userimage/{file_email}', [
    'uses' => 'UserController@getUserImage',
    'as'     => 'account.image'
]);

View

@if (Storage::disk('local')->has($user->email . '-' . $user->id . '.jpg'))
<section class="row new-post">
    <div class="col-md-6 col-md-offset-3">
        <img src  ="{{ route('account.image', ['file_email' => $user->email . '-' . $user->id . '.jpg']) }}" 
             alt  ="" 
             class="img-responsive"
        >
    </div>
</section>
@endif

GitLab Repository link

I believe that this is the solution even more I can not say that the logged in user id === id, should I be passing something can anyone help? I've tried this approach at last

public function getUserImage($file_email)
{
    $user = Auth::user();
    $id = $this->getIdByFileName($file_email);
    if($user->id === $id){
      $file = Storage::disk('local')->get($file_email);
      return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);
    } else {
      // devolve o response com status 401
    }
}

Private Method

private function getIdByFileName($fileName){
$fileEmailArray = explode($fileName,"-");
    $id = explode($fileEmailArray[count($fileEmailArray)-1],".")[0];

}

    
asked by anonymous 12.09.2017 / 07:34

2 answers

0

Walkthrough:

Type in the command line:

  

php artisan make:middleware CheckImageUserMiddleware

go to the folder: App\Http\Middleware and open the file CheckImageUserMiddleware and make the following code:

<?php

namespace App\Http\Middleware;

use Closure;

class CheckImageUserMiddleware
{
    public function handle($request, Closure $next)
    {
        if ($request->user()->id != $request->filename)
        {
            abort(404); // não autorizado.
        }

        return $next($request);
    }
}

After it needs to be registered inside the file app/Http/Kernel.php in the configuration of array $routeMiddleware add another item, with the above class created:

protected $routeMiddleware = [
    'auth' => \App\Http\Middleware\Authenticate::class,
    'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
    'imageuser' => \App\Http\Middleware\CheckImageUserMiddleware::class
];

Finally add this to the route:

Route::get('/userimage/{filename}', 
   [ 'uses' => 'UserController@getUserImage', 
     'as' => 'account.image',
     'middleware' => ['imageuser'] 
   ]); 
    
12.09.2017 / 16:30
0

I found the solution to my problem above this way.

Controller I changed the method that took the image to look like this:

public function getUserImage()
{
    $user  = Auth::user();
    $image ="". $user->email . '-' . $user->id . '.jpg';
    $file  = Storage::disk('local')->get($image);
    return Response::make($file,200,[ 'Content-Type' => 'image/jpeg']);


}

Route In the route that took the image I removed {file_email}.

Route::get('/userimage', [
'uses' => 'UserController@getUserImage',
'as'   => 'account.image'
]);

View This way in the view it is enough just to call the route normally that I can get the image and I do not have the security problem anymore.

 <img src="{{ route('account.image')}}">
    
14.09.2017 / 04:46