我在Laravel 5.6中有一个REST API
用户可以将他们的文件上传到非公共文件夹中。
我的问题是,现在我想让用户只在JWT令牌有效且用户拥有正确权限时才下载文件。
我的实际代码如下:
jquery:
$.ajaxSetup({
headers: {
'Authorization': 'Bearer ' + token
});
$.get('/api//download?' + $.param({
file: encodeURIComponent(fileNonPublicPath) //e.g. company_id/file.pdf
}))
.done((data) => {
console.log('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中接收文件的内容,然后用户无法下载。
什么是不影响存储文件安全性的解决方案?
答案 0 :(得分:0)
如果文件不是,则需要对下载进行流式传输。
#!/bin/sh
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import FirefoxOptions
opts = FirefoxOptions()
opts.add_argument("--headless")
driver = webdriver.Firefox(firefox_options=opts)
driver.get("https://www.exampledomain.com")
username = driver.find_element_by_id("txtUser")
password = driver.find_element_by_id("txtPass")
username.send_keys("XXXXX")
password.send_keys("XXXXX")
driver.find_element_by_name("submit").click()
driver.close()
有时您可能希望将给定操作的字符串响应转换为可下载的响应,而不必将操作的内容写入磁盘。您可以在此方案中使用streamDownload方法。此方法接受回调,文件名和可选的标头数组作为其参数:
response->streamDownload()
答案 1 :(得分:0)
我使用以下解决方案解决了它:
在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
这应该足够安全。