sorry falsche URL:
https://stackoverflow.com/questions/115 ... able-files
Hm, irgendwie habe ich kein Bearbeiten Button gefunden/gesehen, deswegen nochmal die Korrektur zur URL.
Gruß Sandy
Media Verzeichnis schützen
- __blackjack__
- User
- Beiträge: 14013
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@knasan: Ad 1. Gegenfrage, gibt's da was uneleganteres? 
Aber vielleicht erst einmal zu vorhergehenden Problemen. Das fängt mit der Route an, der reguläre Ausdruck ist kaputt, der erlaubt zum Beispiel das hier als Route:
"media" ist fest, bei "something" ist man auf Zeichen der ”word”-Klasse beschränkt, aber danach kann dann wirklich *alles* kommen.
Die Urls für diese Route müssen auch nicht mit "media/" anfangen, denn auch das hier geht:
Einzige Einschränkung: `something_a` und `something_b` müssen aus Zeichen der ”word”-Klasse bestehen. Davor kann *alles* stehen.
In keiner der beiden Varianten lässt sich am Ende allerdings eine Dateiendung mit einem Punkt angeben. Das geht dann also nur für Dateien die keine Dateiendung haben.
Reguläre Ausdrücke sind mächtig, aber auch kompliziert und damit fehleranfällig. `path()` würde ich in der Regel vorziehen. Mir ist nicht so ganz klar was Du da genau mit dem regulären Ausdruck erreichen wolltest, aber das wäre wohl so etwas in diese Richtung:
Bei dem Code der dann in der `listfiles()` bei Dir folgt sind die Pfadoperationen nicht wirklich sicher. Auch wenn der reguläre Ausdruck dich wahrscheinlich schützt, hast Du ja gesehen wie leicht man da Fehler machen kann. Darum würde ich auch danach immer Sicherheitsmassnahmen ergreifen die verhindern das bei absichtlich oder unabsichtlich eingegebenen Daten böse Sachen passieren können, wie beispielsweise jemand der versucht mit "..", "../..", und so weiter über das Wurzelverzeichnis hinaus zu kommen. Aus dem gezeigten Code wird beispielsweise nicht ersichtlich ob Benutzernamen so etwas erlauben, dass man aus einer Kombination aus Benutzernamen ("../../etc/") und URL die mit "/hosts" endet nicht vielleicht doch an die ``/etc/hosts`` auf dem Server heran kommen kann.
Letztlich würde ich das aber sowieso versuchen zu vermeiden selbst zu schreiben. Django bietet da beispielsweise schon eine Abstraktion auf Dateisysteme, so dass man notfalls auch virtuelle Dateisysteme verwenden kann wo die Dateien in Datenbanken gespeichert werden, oder bei Cloudanbietern, oder…
Django selbst bietet da bereits ein `FileSystemStorage` an. Das kümmert sich unter anderem um ein sicheres erstellen eines Pfades, also so das man nicht über das Wurzelverzeichnis heraus kommen kann.
Ungetestet:
Benutzer-ID ist hier eventuell sinnvoller als Benutzername, zumindest wenn das System Änderung des Nutzernamens erlauben sollte.
Dann noch mal Ad 1.: ``.split("/")[1:][0]`` ist etwas umständlich für ``.split("/")[1]``:
Wobei man da bei `split()` auch noch das zweite Argument nutzen kann um unnötige Elemente zu vermeiden:
Ad 2. MVC? View? Welches MVC? Es gibt nicht *das* MVC. Jedes Rahmenwerk hat offenbar eine eigene Meinung dazu wie MVC auszusehen hat, von einzelnen Entwicklern mal ganz abgesehen. Das ist eine nette Theorie die in der Praxis kein wirkliches Entwurfsmuster ist. Denn Entwurfsmuster impliziert ja, dass man ein Muster gefunden und dem einen Namen gegeben hat, damit alle das gleiche darunter verstehen. Das ist bei MVC so ganz und gar nicht der Fall.
Wie Django das sieht steht in der FAQ: https://docs.djangoproject.com/en/2.2/f ... dard-names
Die nennen das auch lieber MTV was sie machen — Model, Template, View.
Aber vielleicht erst einmal zu vorhergehenden Problemen. Das fängt mit der Route an, der reguläre Ausdruck ist kaputt, der erlaubt zum Beispiel das hier als Route:
Code: Alles auswählen
"media/something/really anything goes here 🐁/../../../etc/hosts"
Die Urls für diese Route müssen auch nicht mit "media/" anfangen, denn auch das hier geht:
Code: Alles auswählen
"../../really anything goes here 📭/something_a/something_b"
In keiner der beiden Varianten lässt sich am Ende allerdings eine Dateiendung mit einem Punkt angeben. Das geht dann also nur für Dateien die keine Dateiendung haben.
Reguläre Ausdrücke sind mächtig, aber auch kompliziert und damit fehleranfällig. `path()` würde ich in der Regel vorziehen. Mir ist nicht so ganz klar was Du da genau mit dem regulären Ausdruck erreichen wolltest, aber das wäre wohl so etwas in diese Richtung:
Code: Alles auswählen
path("media/<filename>", views.listfiles, name="listfiles"))
...
def listfiles(request, filename):
...
Letztlich würde ich das aber sowieso versuchen zu vermeiden selbst zu schreiben. Django bietet da beispielsweise schon eine Abstraktion auf Dateisysteme, so dass man notfalls auch virtuelle Dateisysteme verwenden kann wo die Dateien in Datenbanken gespeichert werden, oder bei Cloudanbietern, oder…
Django selbst bietet da bereits ein `FileSystemStorage` an. Das kümmert sich unter anderem um ein sicheres erstellen eines Pfades, also so das man nicht über das Wurzelverzeichnis heraus kommen kann.
Ungetestet:
Code: Alles auswählen
def download_file(request, filename):
if not request.user.is_authenticated():
return HttpResponseForbidden("<h1>User is not logged in</h1>")
try:
file = default_storage.open(os.path.join(str(request.user), filename))
except FileNotFoundError:
return HttpResponseNotFound("<h1>File not found</h1>")
else:
return FileResponse(file)
Dann noch mal Ad 1.: ``.split("/")[1:][0]`` ist etwas umständlich für ``.split("/")[1]``:
Code: Alles auswählen
In [43]: "foo/bar/baz/spam".split("/")
Out[43]: ['foo', 'bar', 'baz', 'spam']
In [44]: "foo/bar/baz/spam".split("/")[1:]
Out[44]: ['bar', 'baz', 'spam']
In [45]: "foo/bar/baz/spam".split("/")[1:][0]
Out[45]: 'bar'
In [46]: "foo/bar/baz/spam".split("/")[1]
Out[46]: 'bar'
Code: Alles auswählen
In [47]: "foo/bar/baz/spam".split("/", 2)
Out[47]: ['foo', 'bar', 'baz/spam']
In [48]: "foo/bar/baz/spam".split("/", 2)[1]
Out[48]: 'bar'
Wie Django das sieht steht in der FAQ: https://docs.djangoproject.com/en/2.2/f ... dard-names
Die nennen das auch lieber MTV was sie machen — Model, Template, View.
“The best book on programming for the layman is »Alice in Wonderland«; but that's because it's the best book on anything for the layman.” — Alan J. Perlis
Hallo ,
danke @__blackjack__,
danke für deine Erklärung, jetzt ist mir auch vieles klar geworden.
Ein path mit optionen (filename) und dann die Funktion diese in die Parameterliste aufnehmen, war mir so nicht klar. Aber dank deines Beispiels ist mir ein licht aufgegangen.
Ich denke, das ich nun verstanden habe wie es geht und werde es in der Datenbank speichern (File im Storage) und die Zugriffe in der DB. Denke so werde ich es hinbekommen.
Sobald ich neuen Code habe, werde ich meine Lösung mal hier posten. Wie ich eben gelernt habe, ist unachtsam im code etwas böses
Gibt es eine Art Security Check für Python entwickelte Webseiten? Der mich auf das eine oder andere Aufmerksam macht oder muss jede Webseite manuell überprüft werden ob diese evtl. Schwachstellen enthält?
danke @__blackjack__,
danke für deine Erklärung, jetzt ist mir auch vieles klar geworden.
Ein path mit optionen (filename) und dann die Funktion diese in die Parameterliste aufnehmen, war mir so nicht klar. Aber dank deines Beispiels ist mir ein licht aufgegangen.
Ich denke, das ich nun verstanden habe wie es geht und werde es in der Datenbank speichern (File im Storage) und die Zugriffe in der DB. Denke so werde ich es hinbekommen.
Sobald ich neuen Code habe, werde ich meine Lösung mal hier posten. Wie ich eben gelernt habe, ist unachtsam im code etwas böses

Gibt es eine Art Security Check für Python entwickelte Webseiten? Der mich auf das eine oder andere Aufmerksam macht oder muss jede Webseite manuell überprüft werden ob diese evtl. Schwachstellen enthält?
Vielleicht hilft das ja weiter, wenn noch nicht bekannt: https://docs.djangoproject.com/en/2.2/h ... checklist/knasan hat geschrieben: Montag 4. November 2019, 22:19 Gibt es eine Art Security Check für Python entwickelte Webseiten? Der mich auf das eine oder andere Aufmerksam macht oder muss jede Webseite manuell überprüft werden ob diese evtl. Schwachstellen enthält?
Ansonsten gibt es diverse generische Werkzeuge für diesen Zweck; etwas python-spezifisches ist mir aber nicht geläufig.
Das Verzeichnis zu Schützen usw über den view kostet zu viel Ressourcen. Ich hatte die Möglichkeit dieses Thema mit einem python django Dozent zu diskutieren. Er hat mir am Ende der Diskussion diese URL gegeben wie man es umsetzen könnte. https://wellfire.co/learn/nginx-django- ... redirects/
Ich dachte, ich teile diesen link mal mit euch
Am Wochenende werde ich mir mal ein Server aufsetzen und das ganze testen.
Gruß Sandy
Ich dachte, ich teile diesen link mal mit euch
Am Wochenende werde ich mir mal ein Server aufsetzen und das ganze testen.
Gruß Sandy
Was den Vorschlag von Sirius3 weiter vorne eine Anleitung für Django zur Seite stelltknasan hat geschrieben: Dienstag 5. November 2019, 21:39 Er hat mir am Ende der Diskussion diese URL gegeben wie man es umsetzen könnte. https://wellfire.co/learn/nginx-django- ... redirects/
