У меня есть REST API в Laravel 5.6
Пользователи могут загружать свой файл в непубличную папку.
Моя проблема в том, что теперь я хочу разрешить пользователю загружать файл только в том случае, если токен JWT действителен и если у пользователя есть необходимые права.
Мой фактический код следующий:
jquery:
$.ajaxSetup({
headers: {
'Authorization': 'Bearer ' + token
});
$.get('/api//download?' + $.param({
file: encodeURIComponent(fileNonPublicPath) //e.g. company_id/file.pdf
}))
.done((data) => {
console.info('file content', data);
})
.fail((err) => {
console.error(err);
});
Контроллер Laravel:
$file = urldecode($request->input('file'));
$user = JWTAuth::toUser($request->token);
if (checkUserRole($user,$file){
$pathToFile = Storage::disk('documents')->getDriver()->getAdapter()->applyPathPrefix($file);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $pathToFile);
finfo_close($finfo);
$headers = array('Content-Type' => $mime,);
return response()->download($pathToFile, 'originalfilename', $headers);
}
return response()->json([], 403); //forbidden
Этот код работает нормально, за исключением того, что браузер получает содержимое файла в ajax, а затем пользователь не может его загрузить.
Какое решение не ставит под угрозу безопасность хранимых файлов?






Вам необходимо выполнить потоковую загрузку, если это не файл.
response->streamDownload()
Sometimes you may wish to turn the string response of a given operation into a downloadable response without having to write the contents of the operation to disk. You may use the streamDownload method in this scenario. This method accepts a callback, file name, and an optional array of headers as its arguments:
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');
Я решил это с помощью следующего решения:
в файле javascript:
// onclick callback:
window.location = '/download?' + $.param({
token: encodeURIComponent(STRING_TOKEN),
file: encodeURIComponent(file)
});
Создайте новый неохраняемый маршрут в web.php
Route::get('/download', 'UploadController@download');
В UploadController:
$file = urldecode($request->input('file'));
$token = urldecode($request->input('token'));
//This doesn't work
// $user = JWTAuth::toUser($token);
// Then I used the same lib that JWTAuth uses to encode/decode the token
$secret = config('jwt.secret');
$jws = SimpleJWS::load($token);
if (!$jws->isValid($secret)) {
return response()->json([], 401); // unauthorized
}
$payload = $jws->getPayload();
$userId = User::find($payload["user"]["id"]);
$user = App\User::find($userId);
if (checkUserRole($user,$file){
$pathToFile = Storage::disk('documents')->getDriver()->getAdapter()->applyPathPrefix($file);
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $pathToFile);
finfo_close($finfo);
$headers = array('Content-Type' => $mime,);
return response()->download($pathToFile, 'originalfilename', $headers);
}
return response()->json([], 403); //forbidden
Это должно быть достаточно безопасно.
Спасибо за ваш ответ. Можете ли вы привести пример с моим кодом? Спасибо