Zablokowanie pobierania plików statycznych za pomocą bezpośredniego URL

0

Witam,
Chcę w swojej aplikacji webowej dodać funkcjonalność generowania i exportowania plików excelowych z poszczególnych tabel bazy danych.
Napisałem kontroler z pomocą poradnika do biblioteki EPPlus. Kontroler ten tworzy, zapisuje plik .xlsx w folderze wwwroot oraz zwraca do widoku link dzięki któremu możemy pobrać ten plik.

public async Task<IActionResult> Export()
        {
            string folder = _hostingEnvironment.WebRootPath;
            string excelName = $"UserList-{DateTime.Now.ToString("yyyyMMddHHmmssfff")}.xlsx";
            string downloadUrl = string.Format("{0}://{1}/{2}", Request.Scheme, Request.Host, excelName);
            FileInfo file = new FileInfo(Path.Combine(folder, excelName));
            if (file.Exists)
            {
                file.Delete();
                file = new FileInfo(Path.Combine(folder, excelName));
            }

            await Task.Yield();

            List<UserInfo> list = new List<UserInfo>
            {
                new UserInfo{UserName="John", Age=20},
                new UserInfo{UserName="Peter", Age=23}
            };

            using(var package = new ExcelPackage(file))
            {
                var workSheet = package.Workbook.Worksheets.Add("Sheet1");
                workSheet.Cells.LoadFromCollection(list, true);
                package.Save();
            }

            return View("Result", downloadUrl);
        }

Po wykonaniu tej akcji w widoku ukazuje się link w stylu localhost:43356/UserList-XXXXXXXXX.xlsx. Dzięki temu linku każdy użytkownik może pobrać stworzony plik.
Oczywiście gdyby w wwwroot był jakiś plik "test.txt" to KAŻDY użytkownik mógłby go ściągnąć wpisując adres
localhost:43356/test.txt. Nie chcę aby coś takiego miało miejsce. Da się jakoś zablokować pobieranie plików z wwwroot za pomocą bezpośredniego URL?
Chciałbym osiągnąć efekt, że w bazie danych mam nazwy plików i powiązanych z nimi userów którzy mają do danego pliku dostęp. Tylko ci user'rzy którzy mają dostęp do pliku mogą go pobrać. W tym celu muszę jakoś zablokować te bezpośrednie url'y.

Jeśli ten sposób(tworzenie plików w wwwroot) jest zły, proszę o pomoc jak tego typu rzeczy się wykonuje w ASP.NET core.

0

Można na różne sposoby. Jeden z prostszych to trzymać pliki poza publicznymi folderami. Tylko wtedy musialbys napisac wlasny kontroler wysylajacy pliki uprawnionym osobom.

1

IMHO tak.

3

Koszernym zastosowaniem wwwroot jest przechowywanie statycznych plików wykorzystywanych przez aplikację. Czyli np ikonek, zdjęć, skryptów itp.
Wrzucanie do niego rzeczy generowanych w runtime jest słabym pomysłem ponieważ może się okazać że przy kolejnym deployu cały ten misternie zbierany content zniknie. A do tego w bazie danych będzie masa powiązań do plików które już trafiły do binarnego piekła.
Osobiście trzymałbym takiego rodzaju pliki z dala od aplikacji, dodał sobie odpowiedni kontroler wraz z całą infrastrukturą do obsługi plików i spał spokojniej.

0

Dzięki wam!
Już mniej więcej czaję jak to działa :)

2

tylko pamiętaj, żadnych ścieżek/nazw plików jako parametr z frontu.

0

Czyli w jaki sposób powiedzieć serwerowi jaki plik chcemy pobrać?

1

Najprościej będzie jak podczas generowania pliku i zapisu jego metadanych do bazy wygenerujesz mu guid i tego właśnie guida użyjesz jako identyfikatora. Nie używasz wtedy żadnych nazw ani inkrementowalnej wartości po której łatwo jest zaciągnąć wszelkie możliwe zasoby (jeśli okaże się, że zabezpieczenia aplikacji są niepoprawnie zaimplementowane). Url może wyglądać wtedy np tak:

https://myapp.com/reports/C82F884FDF3543058C949ACD52EA7E96

0

Czyli w skrócie i uproszczeniu
dla zalogowanego użytkownika zwracam listę GUID, do których ten użytkownik ma dostęp, i on za ich pomocą może on zobaczyć dane plików lub pobrać dany plik. Oczywiście przed tymi operacjami upewniam się ponownie, czy dany użytkownik ma prawo do tego pliku?

1

Zależy jak tam te uprawnienia sobie realizujesz ale powinno (imo) to wyglądać tak, że

user chce pobrać plik z http://site.com/Storage/43b0044c-583f-4b4f-9c0f-280f96476b5d, to następnie pobierany jest z bazy obiekt, który służy jako abstrakcja nad plikiem

będzie on miał pewnie ten id (np. ten guid), name (od usera) typu dupa.jpg, prawdziwy file name na dysku generowany przez aplikację np. 43b0044c lub 101 / 101.jpg - nie wiem co tam sobie wymyślisz, to jest wewnętrzna nazwa, więc chyba trudno coś tu zrobić bardzo źle, jakiś file size - no generalnie co tam potrzebujesz trzymać w tej bazie.

sprawdzasz czy ten user ma dostęp do tego pliku i jeżeli ma, to mu go zwracasz - https://stackoverflow.com/questions/42460198/return-file-in-asp-net-core-web-api

1 użytkowników online, w tym zalogowanych: 0, gości: 1