
Wir sind vor Kurzem von Apache zu Nginx gewechselt. Unter Apache war es früher ganz einfach: einfach ein paar Sachen in .htaccess einfügen und fertig.
RewriteEngine on
RewriteBase /
# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s
# pass the rest of the request into index.php to handle
RewriteRule ^(.*)$ /index.php/$1 [L]
Das Obige hat hervorragend dazu gedient, URLs zu bereinigen und index.php alle Anfragen verarbeiten zu lassen. Aber in Nginx mussten wir jede eindeutige URL im Standortblock neu schreiben. Dies ist jedoch nicht „automatisch“ wie bei Apache.
Einige Beispiele unseres Rewrite-Location-Blocks
location / {
try_files $uri $uri/ /index.php;
}
location /p {
rewrite ^/p(?:/([a-z_]+))?$ /index.php?p=$1 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}
location /about_us {
rewrite ^/about_us /index.php?about_us last;
try_files $uri $uri/ /index.php;
}
location /search {
rewrite ^/search/(.*) /index.php?search=$1;
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
das obige funktioniert gut bei sauberen URLs, aber wenn wir zum Beispiel Seiten abrufen müssen
/p/alle_artikel/benutzer/ABC/seite/2
/index.php?p=alle_artikel&user=ABC&page=2
Wir haben es versucht
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
dies funktioniert nur, wenn wir es in einem separaten Standortblock platzieren
location /page/all_articles {
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
try_files $uri $uri/ /index.php;
}
und wenn dies geschieht, wird es nicht zulassen,
/p/alle_artikel/Benutzer/ABC
Laden.
außerdem würden Suchergebnisseiten überhaupt nicht funktionieren.
Ein weiteres Problem, auf das wir gestoßen sind, betrifft den Ordner .htaccess
Order deny,allow
Deny from all
Options -Indexes
Unter Apache würde dies jeden Zugriff auf diesen Ordner und die Dateien außer dem PHP-Skript verhindern. Wir haben versucht,
location /(data|img)/ {
deny all;
return 404;
}
Es blockiert zwar den Zugriff auf den Ordner, aber wenn Sie den Dateinamen angeben, wird es trotzdem ausgeführt, ohne beispielsweise den Zugriff zu verweigern;
/data/backup_01012020.zip unter Apache .htaccess, nur bestimmte Benutzer durften darauf zugreifen, während sie angemeldet waren. Außerhalb davon verweigert Apache jeglichen Zugriff. Aber unter Nginx gibt es trotzdem eine 404-Fehlermeldung, wenn versucht wird, auf /data/ zuzugreifen. Selbst wenn Sie nicht angemeldet sind, wird die Datei backup_01012020.zip sofort bereitgestellt.
Jetzt wissen wir nicht, was wir tun können, was mit Apache früher ein Kinderspiel war. Unsere Anwendung basiert auf PHP und index.php kann alle sauberen URL-Anfragen verarbeiten. Es wäre toll gewesen, wenn Nginx einfach alle Anfragen an den Index übergeben und ihn die Verarbeitung überlassen hätte, anstatt jede Menge Umschreibungen und Standortsperren vorzunehmen. Jede Hilfe wäre toll.
Antwort1
Vielleicht interessieren Sie sich für die Fragen mit demTag umschreiben, da es viele Variationen Ihres Problems enthält.
Ihre Apache-Umschreibregel:
RewriteRule ^(.*)$ /index.php/$1 [L]
hängt die gesamte Anfrage-URI an /index.php
. InnginxDieWegder URI (normalisiert) ist verfügbar in der$uriVariable. Wenn Sie auch die Abfrageargumente benötigen, können Sie die$Anforderungs-URIstattdessen.
Eine strikte Übersetzung Ihrer Umschreiberegeln wäre daher:
location / {
# Size zero static files are served.
# I don't believe that is an issue.
try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# Probably duplicates the contents of fastcgi-php.conf
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
}
Ihre deny
Anweisung zum /(data|img)/
Standort funktioniert nicht, da Sie eine Präfixübereinstimmung anstelle einer Regex-Übereinstimmung verwenden:
location ~ ^/(data|img)/ {
# Only one is required
deny all;
# return 404;
}
Antwort2
Lösung zum Umschreiben
location /search {
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
rewrite ^/search/(.*) /index.php?search=$1 last;
try_files $uri $uri/ /index.php;
}
location /p/all_articles {
rewrite ^/p/all_articles/user/(.*)/page(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&page=$2 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}
Beachten Sie, dass ich nur Zeilen ausgetauscht habe. Dank anRichard Smith
Dank anPiotr P. Karwasz, für die andere Lösung könnte es jemandem helfen, dessen Skript 100 % kompatibel ist und saubere URLs selbst verarbeiten kann.
location / {
# Size zero static files are served.
# I don't believe that is an issue.
try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# Probably duplicates the contents of fastcgi-php.conf
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
}
Die obige Lösung ist eine Möglichkeit, solange Ihr Skript zu 100 % mit einer sauberen URL funktioniert. Hier müssen Sie nicht Hunderte von Umschreibe-Standortblöcken einfügen, und nginx hängt die gesamte Anforderungs-URI an /index.php an, was sehr interessant und hilfreich ist. Wahrscheinlich ist dies die richtige Lösung, aber in meinem Fall war mein Skript nicht 100 % kompatibel damit. Trotzdem ist dies eine gute, clevere Lösung.
Lösung zum Verhindern des Zugriffs auf Ordner und Dateien
location ~ ^/(data|img)/ {
# Only one is required
deny all;
# return 404;
}
Anerkennung anPiotr P. Karwaszdarauf hingewiesen, dass es deny all
durch etwas überschrieben wurde, das Problem wurde durch eine saubere Serverblockierung gelöst. Stellen Sie außerdem sicher, dass Sie entweder deny all;
oder verwenden return 404;
, aber nicht zusammen.