it-swarm.com.de

Apache 2.4 <Directory> mit regulären Ausdrücken - ist der Alternationsoperator defekt oder bin ich verwirrt?

Ich habe mehrere Dokumentstammverzeichnisse, /opt/lampp/htdocs/proj1, /opt/lampp/proj2 usw., die über einen AuthType Basic -Passwortschutz verfügen. Ich möchte, dass die uploads -Unterverzeichnisbäume kein Kennwort erfordern. Mit der Ausnahme, dass der private -Unterverzeichnisbaum von uploads überhaupt keinen Zugriff zulassen sollte. Laut http://httpd.Apache.org/docs/current/mod/core.html#directory :

Reguläre Ausdrücke werden erst berücksichtigt, nachdem alle normalen Abschnitte angewendet wurden. Dann werden alle regulären Ausdrücke in der Reihenfolge getestet, in der sie in der Konfigurationsdatei aufgeführt sind.

Also habe ich diese Direktiven benutzt:

#==========================================================
# regexp enables access to images without login (needed for wp_sideload_image)
<Directory ~ "/opt/lampp/htdocs/[^/]*/public/(uploads|wp/wp-content/uploads)">
    Require all granted
</Directory>

#==========================================================
# regexp protects private uploads unconditionally
# regexps processed in source order, so MUST BE AFTER ENABLING IMAGES
<Directory ~ "/opt/lampp/htdocs/[^/]*/public/uploads/private">
    Require all denied
</Directory>

Was ich fand, war, dass die Require all denied -Direktive nicht wirksam war, auf alles unter Uploads konnte ohne ein Passwort zugegriffen werden, einschließlich Dinge unter privat. Aus Spaß habe ich versucht, den alternierenden Ausdruck zu entfernen und den ersten Block zu erstellen:

<Directory ~ "/opt/lampp/htdocs/[^/]*/public/uploads">
    Require all granted
</Directory>

Und zu meiner Überraschung (und Freude) funktionierten die Dinge so, wie ich es wollte. So kann ich den Effekt des ursprünglichen regulären Ausdrucks durch Hinzufügen eines weiteren <Directory> erhalten:

<Directory ~ "/opt/lampp/htdocs/[^/]*/public/wp/wp-content/uploads">
    Require all granted
</Directory>

Während das funktioniert, kann ich auch normale <Directory> Blöcke mit einem '*' Platzhalter für die Ebene unterhalb von htdocs verwenden. Ich dachte, es wäre prägnanter, das reguläre Ausdrucksformat zu verwenden. Ich möchte jedoch immer noch regexp für den privaten Bereich verwenden, da dieser nach den Anweisungen verarbeitet werden muss, die den Zugriff gewähren.

Kann jemand erklären, warum der ursprüngliche Code nicht funktioniert? Die Apache-Dokumente geben an, dass sie PCRE verwenden, und der Ausdruck mit Alternation funktioniert gut mit egrep. Außerdem sehe ich nicht, wie sich dieser Ausdruck auf das nachfolgende Require all denied auswirken könnte, da es sich bei beiden um reguläre Ausdrücke handelt, die in der Quellreihenfolge verarbeitet werden sollen. Die abgelehnte Richtlinie sollte also auf jeden Fall Vorrang haben, nicht wahr? Das passiert, wenn ich den Wechsel durch zwei separate reguläre Ausdrücke ersetze. Was vermisse ich?

BEARBEITEN: Als ich dies gepostet habe, hatte ich offensichtlich einen Hirnfurz-Moment, in dem ich dachte, dass die Nicht-Regexp-Regel von "shortest path first" bedeutet, dass ich ein Regexp verwenden muss, um sicherzustellen, dass der "Require all denied" verarbeitet wird spät genug. Obwohl es unter "uploads" längere Pfade geben könnte als unter "uploads/private", gäbe es in diesen Fällen keine Übereinstimmung mit "uploads/private", so dass diese Pfade ohnehin nicht verboten werden sollten . Daher glaube ich, dass die "beste" Lösung für meine aktuelle Situation darin besteht, die Verwendung von "regexp" Matching ganz zu eliminieren und drei normale "<Directory>" Direktiven mit Platzhaltern zu verwenden, die den mit Regexps oben gezeigten ähnlich sind, aber die ersetzen "[^/]*" mit dem Shell-Platzhalter "*" neu ausdrücken. Das funktioniert einwandfrei und ist wahrscheinlich Mikrosekunden schneller :-)

Ich möchte jedoch immer noch wissen, warum mein ursprünglicher Code nicht funktioniert hat. Es scheint mir immer noch, dass Apache die Direktive, die den Regexp-Operator "|" enthält, falsch behandelt hat.

3
sootsnoot

Diese Frage brachte mich dazu, einige Dinge zu mischen. Dieser funktioniert erwartungsgemäß gemäß dem, was ich mit dem Operator | getestet habe, und nutzt die Möglichkeit in Apache 2.4, das Zeichen $ als Zeilenende zu verwenden:

<DirectoryMatch "/opt/lampp/htdocs/[^/]*/public/(uploads(/[^/]*)?|(wp/wp-content/uploads(/[^/]*)?))$">
    Require all granted
</DirectoryMatch>
<DirectoryMatch "/opt/lampp/htdocs/[^/]*/public/uploads/private">
    Require all denied
</DirectoryMatch>

Ich dachte, ich verstehe teilweise, warum dieses Verhalten, aber tatsächlich habe ich es nicht verstanden. Ich denke, das ist etwas, was ich an die Apache-Mailingliste fragen werde.

1
Zimmi

Mein einziger Vorschlag wäre, dem regulären Ausdruck mehr Klammern hinzuzufügen:

<Directory ~ "/opt/lampp/htdocs/[^/]*/public/(uploads|(wp/wp-content/uploads))">

Die Reihenfolge der Operationen mit | und / könnte Teil des Problems sein.

0