i have a download function receiving the filename by $_GET
and i want to prevent users of downloading other files changing the path and accessing other files in the system.
method:
function actionDownload($arquivo) {
try {
$filepath = \Yii::getAlias('@webroot') . '/files/coordenadas/'. $arquivo;
if (file_exists($filepath)){
return \Yii::$app->getResponse()->sendFile(\Yii::getAlias('@webroot') . '/files/coordenadas/'. $arquivo, $arquivo);
}
}
catch (\Exception $exception) {
throw new NotFoundHttpException("Arquivo não encontrado");
}
}
the route to download the method:
http://example.com/converter-coordenadas/download?arquivo=geografica-utm-20200830171051.xlsx
if someone change the arquivo
variable to another valid path it will be able to download other files. How prevent that, but keeping the function receiving the file name in a url param?
the situation that i have is:
I don't have any other information to make a relation with the file, like an user id.
As @GetSet explained in the comments, the biggest problem is procedural. One way to do this correctly is as follows:
Upload the file to your server and save the reference in database (you already doing) and generate an unique ID for this file (or for this download). This ID will be saved in a database field, for example with the name: "donwload_id"
Then in the view (when you are creating the link for the download):
Html::a('Download', [Url::to('donwload-action'), 'download_id' => $model- >download_id]);
In your controller, You will know how to find the file by its unique identifier (download_id).
No one knows how you have generated this ID and therefore it is more difficult for anyone to be able to generate it again. Also you can limit the time available to download the file by setting an expiration date to the link.