-4

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:

  1. the user upload a file through ajax
  2. i convert this file and return the filename
  3. create a download button with the link to the new file.

I don't have any other information to make a relation with the file, like an user id.

4
  • 4
    Probably not have your download file exposed in url at all. Instead have an id that references the file Commented Aug 30, 2020 at 21:38
  • 1
    Or you can encrypt the filename and store in separate DB field along with original name at the time when you save the file, and show user only encrypted name. In your action you check if hash exist in DB and get needed original filename. Same technic is used on restore password or validate email address. You can take a look there. Commented Aug 30, 2020 at 22:10
  • I was hoping getting a lazy way to do it, using something native in php to only allow to access the path that i want, but that is a more elegant way. thanks @SergheiLeonenco Commented Aug 30, 2020 at 22:40
  • 1
    You are very welcome Commented Aug 30, 2020 at 22:41

1 Answer 1

1

As @GetSet explained in the comments, the biggest problem is procedural. One way to do this correctly is as follows:

  1. 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"

  2. 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]);

  3. 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.