irek86pl / 12.03.2020

.htaccess bez tajemnic – sztuczki z serwerem Apache

.htaccess bez tajemnic – sztuczki z serwerem Apache

Istnieją różne sztuczki, o których wiele osób słyszało, ale nie każdy je stosuje. Jeżeli prowadzisz stronę internetową i masz dostęp do pliku .htaccess na serwerze Apache, co obecnie jest już standardem, możesz w prosty sposób całkowicie zmienić jej funkcjonowanie.

Plik .htaccess jest domyślnym plikiem, za pomocą którego można zmieniać ustawienia serwera Apache dla katalogów. Mechanizm .htaccess jest zazwyczaj domyślnie włączony, jeśli jednak administrator z jakiejś przyczyny w pliku konfiguracyjnym Apache’a zawarł opcję

AllowOverride None

to .htaccess nie zadziała. Dowcipni administratorzy mogą zrobić nam niespodziankę i w ustawieniach Apache’a zadeklarować inną niż domyślną nazwę .htaccess. Umożliwia im to dyrektywa

AccessFileName .ustawienia

W takim przypadku zamiast .htaccess będziemy edytować plik .ustawienia, ponieważ to właśnie on odpowiadać będzie za konfigurację serwera. Na szczęście ma to miejsce bardzo rzadko.

Zazwyczaj plik .htaccess umieszczany jest w głównym katalogu, jednak można stworzyć go w każdym innym istniejącym. Zapisy zawarte w tym pliku funkcjonują dla danego katalogu oraz wszystkich podkatalogów w nim się znajdujących. Co można osiągnąć za pomocą tego pliku?

Okaże się przydatny przy wszelkiego rodzaju przekierowaniach, tworzeniu komunikatów błędów i zmiany sposobu dostępu do naszej strony. Przy każdorazowym odświeżeniu plik ten jest ponownie wczytywany, w związku z tym każda zmiana jest od razu widoczna.

Kiedy mamy już pewność, że istnieje możliwość zmiany ustawień za pomocą pliku, należy go stworzyć (chyba że istnieje) i zabrać się do edycji. Zbiór .htaccess powinien mieć uprawnienia 644 (nadane przez polecenie chmod).

Pozwoli to na dostęp do pliku przez serwer, ale uniemożliwi jego zmianę z poziomu przeglądarki:

Chmod 644 .htaccess

Zanim przystąpimy do pierwszych zapisów w pliku, warto wspomnieć, że komentarze w pliku .htaccess wstawia się poprzedzając je znakiem #

#komentarz
#kolejna linia komentowana

Po każdej linii zapisu musi także nastąpić enter. Pisanie jednym ciągiem bez załamywania wierszy może sprawić, że wpisy nie będą funkcjonować. Tak samo ostatnia linia w pliku .htaccess powinna być linią pustą.

Na początek warto zacząć od określenia domyślnego pliku strony WWW. W tym celu wykorzystamy dyrektywę {stala}DirectoryIndex{/stala}. Można podać kilka nazw plików, trzeba jednak pamiętać o rozdzieleniu ich spacjami. Kolejność ma znaczenie – jeśli pierwszy nie zostanie znaleziony, automatycznie zostanie wczytany drugi.

DirectoryIndex index.html index.php awaria.html

Powyższa instrukcja pokazuje kolejność wczytywania plików. Jeżeli zostanie odnaleziony plik index.html, to właśnie on będzie traktowany jako domyślny, a w przypadku jego braku, domyślnym będzie index.php itd. Korzystanie z tego typu dyrektywy bywa przydatne, jeśli główny plik strony ma inną nazwę niż index.php (wtedy zapis może wyglądać następująco):

DirectoryIndex start.html

A także, gdy planujemy zmiany na naszej stronie WWW. Wtedy bez zbędnej przebudowy możemy stworzyć stronę awaryjną, którą ustanawiamy jako domyślną:

DirectoryIndex awaria.html

Po skończeniu wprowadzania zmian można bez problemu powrócić do wcześniejszych ustawień.

Zmiana powiązań typów plików

MimeType to rozszerzenia, które zwracane są przeglądarce po znalezieniu na serwerze danego typu pliku. Dany typ pliku powoduje konkretną reakcję ze strony przeglądarki. Zazwyczaj jest to otwarcie programu obsługującego plik o tym rozszerzeniu. Większość rozszerzeń jest zdefiniowana w domyślnej konfiguracji serwera, jednak czasem może się zdarzyć, że będziemy chcieć dodać lub zmienić daną definicję np.:

AddType text/html .txt
#pliki z rozszerzeniem .txt będą odczytywane jako pliki .html

Taki zapis sprawia, że wszystkie pliki .txt będą rozpoznawane jako zwykle pliki .html. Aby wymusić otwieranie plików skompresowanych w odpowiednich aplikacjach, wystarczy skorzystać z odpowiedniej definicji. Często w przeglądarkach ten typ plików jest odczytywany w formie niezrozumiałego tekstu.

AddType application/zip .zip
AddType application/x-gzip .gz
AddType application/x-gtar .gtar
AddType application/x-rar-compressed .rar
AddType application/octet-stream .dmg
AddType application/x-7z-compressed .7z

Sposób przypisania większości znanych formatów do aplikacji zawarto w listingu 1.

#css, html, xml, asp, flash i inne
AddType text/css .css
AddType application/xhtml+xml .xhtml
AddType text/html .shtml
AddType text/xml .xml
AddType text/html .asp
Addtype application/x-httpd-php .php
AddType application/x-shockwave-flash .swf
AddType application/x-director .dir .dcr .dxr .fgd
AddType application/x-authorware-map .aam
AddType application/x-authorware-seg .aas
AddType application/x-authorware-bin .aab
AddType image/x-freehand .fh4 .fh5 .fh7 .fhc .fh
AddType application/x-java-applet .class

# dokumenty
AddType application/pdf .pdf
AddType application/msword .doc

#multimedia
AddType audio/mpeg .mp3
AddType video/x-msvideo .avi
AddType audio/x-wav .wav
AddType video/quicktime .mov .qt
AddType video/x-ms-asf .asf .asx
AddType audio/x-ms-wma .wma
AddType audio/x-ms-wax .wax
AddType video/x-ms-wmv .wmv
AddType video/x-ms-wvx .wvx
AddType video/x-ms-wm .wm
AddType video/x-ms-wmx .wmx
AddType application/x-ms-wmz .wmz
AddType application/x-ms-wmd .wmd

#skompresowane
AddType application/zip .zip
AddType application/x-gzip .gz
AddType application/x-gtar .gtar
AddType application/x-rar-compressed .rar
AddType application/octet-stream .dmg
AddType application/x-7z-compressed .7z

#graficzne
Addtype image/jpg .jpg
Addtype image/gif .gif

#pozostałe
AddType application/x-bittorrent .torrent
AddType application/vnd.rn-realmedia .rm
AddType audio/vnd.rn-realaudio .ra .ram
AddType video/vnd.rn-realvideo .rv

Możemy również wymusić na przeglądarce pobieranie plików zamiast ich automatycznego odczytywania:

AddType application/octet-stream .pdf .gz

Taki zapis spowoduje, że dokumenty w formacie .pdf oraz .gz będą pobierane, a nie otwierane przez domyślną aplikacje. Warto wspomnieć o jeszcze jednej prostej, ale przydatnej opcji, której nie sposób pominąć. Edytując plik .htaccess, można szybko dokonać zmiany kodowania dokumentów:

AddDefaultCharset ISO-8859-1
AddDefaultCharset ISO-8859-2

Subdomeny

Załóżmy, że dysponujemy utworzoną subdomeną www.sub.strona.pl. Zadanie będzie polegało na przekierowaniu jej na odpowiedni katalog przy użyciu pliku .htaccess. Zacznijmy od przekierowania subdomeny na odpowiedni katalog bez konieczności zaglądania do panelu administracyjnego domeny:

RewriteCond %{HTTP_HOST} sub.strona.pl
RewriteCond %{REQUEST_URI} !sub/
RewriteRule (.*) sub/ [L]

Ten zapis sprawi, że użytkownik, który wejdzie na adres www.sub.strona.pl, tak naprawdę zostanie przeniesiony na www.strona.pl/sub. Jak powinien w takim razie wyglądać zapis, aby w pasku adresu zamiast {stala}www.strona.pl/sub{/stala} zobaczyć adres subdomeny {stala}www.sub.strona.pl?{/stala} Umożliwi to dodanie do .htaccess kilku linijek kodu:

RewriteCond %{HTTP_HOST} www.strona.pl [NC]
RewriteCond %{REQUEST_URI} sub/
RewriteRule (.*) http://www.sub.strona.pl [L]

I gotowe. Teraz po wejściu do katalogu {stala}/sub{/stala} z pozycji przeglądarki, w pasku adresu zobaczymy www.sub.strona.pl. Jeżeli rzecz dotyczy kilku subdomen, można teoretycznie powielać wpis w pliku .htaccess:

RewriteCond %{HTTP_HOST} sub.strona.pl
RewriteCond %{REQUEST_URI} !sub/
RewriteRule (.*) sub/ [L]
RewriteCond %{HTTP_HOST} sub2.strona.pl
RewriteCond %{REQUEST_URI} !sub2/
RewriteRule (.*) sub2/ [L]

Jednak przy większej liczbie adresów mija się to z celem. Warto wtedy skorzystać z wyrażeń regularnych i zastosować uniwersalny zapis, który będzie pasował do wszystkich katalogów:

RewriteCond %{HTTP_HOST} strona.pl [NC]
RewriteCond %{HTTP_HOST} (.*).strona.pl [NC]
RewriteRule .* /%2%{REQUEST_URI}

Tak samo wygląda sprawa w drugą stronę. Zamiast dodać wiele linijek zbędnego kodu, wystarczy stworzyć definicję, która obejmie wszystkie adresy. Dla przykładu:

RewriteCond %{HTTP_HOST} strona.pl [NC]
RewriteCond %{REQUEST_URI} ^(.+)/$
RewriteRule .* http://%1.strona.pl [L]

Druga linijka odpowiada za znalezienie jakiegoś znaku, czyli np. nazwy naszego katalogu z wcześniejszego przykładu. Należy zwrócić uwagę, że zastosowany został zapis (.+). Użycie w tym miejscu (.*) również dałoby efekt, ale napotkalibyśmy problemy przy wpisywaniu adresu strony głównej www.strona.pl, ponieważ taki zapis
dopuszcza również wstawienie pustego znaku.

Należy przy tym uwzględnić adresy z www i bez www. Z tego powodu do naszych zapisów dodamy warunek za to odpowiedzialny {stala}!^(www\\.)?{/stala}. Czyli ostateczny kod będzie następujący:

RewriteCond %{HTTP_HOST} !^(www\.)?strona.pl$[NC]
RewriteCond %{REQUEST_URI} ^(.+)/$
RewriteRule .* http://%1.strona.pl [L]

Dzięki temu bez względu na to, czy wpiszemy {stala}http://www.strona.pl/sub/{/stala}, czy {stala}http://strona.pl/sub/{/stala}, adres w przeglądarce będzie zawsze miał postaćhttp://sub.strona.pl.

Zmienne globalne

Zmienne przeglądarki

HTTP_USER_AGENT – identyfikator przeglądarki
HTTP_REFERER – adres z przekierowania
HTTP_HOST – adres hosta, który jest wywoływany
HTTP_CONNECTION – tryb połączenia
HTTP_COOKIE – zawiera cookie
HTTP_ACCEPT – dokumenty jakie przyjmuje przeglądarka
HTTP_ACCEPT_LANGUAGE – język przeglądarki
HTTP_ACCEPT_ENCODING – czy przeglądarka akceptuje skompresowane pliki
HTTP_ACCEPT_CHARSET – akceptowane kodowanie dokumentu
HTTP_CONNECTION – tryb połączenia

Zmienne wywołania

REMOTE_ADDR – adres IP użytkownika
REMOTE – host użytkownika
REMOTE_USER – nazwa użytkownika
REMOTE_PORT – port wywołania
AUTH_TYPE – rodzaj autoryzacji ( Basic/Digest)

Zmienne z informacją o działającym skrypcie

SCRIPT_URL – adres logiczny (zmienna z informacją o skrypcie)
SCRIPT_URI pełen adres wraz z hostem (zmienna z informacją o skrypcie)
SCRIPT_FILNAME – nazwa pliku wraz ze ścieżka (zmienna z informacją o skrypcie)
SCRIPT_NAME – nazwa skryptu

Zmienne z informacją o zapytaniu

REQUEST_FILNAME – pełna ścieżka do pliku
REQUEST_URI – zawiera pełen adres wywołania

Zmienne mod_rewrite

QUERY_STRING – informacja o parametrach przesyłanych do skryptu
THE_REQUEST – kompletne wysyłane zapytanie HTTP

Zmienne serwera

SERVER_ADMIN – e-mail admina
SERVER_NAME – adres serwera
SERVER_ADDR – adres IP serwera
SERVER_PORT – adres portu
SERVER_ID – identyfikator
SERVER_PROTOCOL – informacje o protokole (np.: zazwyczaj HTTP/1.1)
DOCUMENT_ROOT – ścieżka do głównego katalogu

Zmienne związane z czasem

TIME_YEAR – obecny rok
TIME_MON – miesiąc
TIME_DAY – dzień
TIME_HOUR – godzina
TIME_MIN – minuty
TIME – aktualny czas w postaci yyyymmddhhmmss

Inne zmienne

PATH_INFO zawiera dopełnienie ścieżki
REDIRECT_URL oryginalny adres przed przekierowaniem

Blokowanie

Dostęp do strony można także z powodzeniem zablokować, stosując mod_rewrite. Jeśli masz podejrzenia, że pewne zasoby strony, np. grafiki lub style, są nielegalnie wykorzystywane przez inną witrynę, warto zablokować jej dostęp. Do pliku .htaccess należy dopisać:

RewriteCond %{HTTP_REFERER} niechciany\.com [NC]
RewriteRule .* - [F]

W pierwszej linii wskazujemy adres, z którego nie życzymy sobie wejść na stronę. Druga linia odpowiada za wyświetlanie strony z błędem 403.

Dokładne znaczenie {stala}HTTP_REFERER{/stala} i innych zmiennych globalnych zostało zawarte w ramce.

MIME type w mod_rewrite

Zmiana sposobu odczytywania plików była już poruszana w tym artykule, warto jednak wspomnieć, że również przy użyciu mechanizmu mod_rewrite możliwe jest nadanie odpowiednich MIME Type. Do tej pory poznaliśmy metodę korzystającą z dyrektywy AddType:

AddType application/x-7z-compressed .7z

co oznaczało, że dla plików z rozszerzeniem .7z domyślną aplikacją jest 7-zip. W poniższym przykładzie zastosowana została dyrektywa RewriteRule, która wszystkie pliki .php(s) będzie odczytywać jako .phps:

RewriteRule ^(.+\.php)s$  [T=application/x-httpd-php-source]

Standardowo {stala}^ i ${/stala} wyznaczają początek i koniec zapisu, $1 to zmienna, a atrybut to {stala}[T=MIME type]{/stala}.

ForceType

Jeżeli zdarzy się, że mod_rewrite będzie wyłączony na naszym serwerze, wystarczy skorzystać z ForceType. Załóżmy, że zamiast {stala}www.strona.pl/index.php{/stala}, chcemy uzyskać {stala}www.strona.pl/index{/stala}.

W tym celu tworzymy w pliku .htaccess zapis:

DirectoryIndex index
ForceType application/x-httpd-php


Pierwsza linia to omówione już wcześniej wskazanie domyślnego pliku startowego (przydaje się, gdy skasujemy rozszerzenie w pliku index. php). Dalej mamy zapis ForceType, który każdorazowo należy stworzyć: Sposób odczytywania pliku

W naszym przykładzie chcemy, aby index był odczytywany jako plik index.php dlatego zastosowane zostało {stala}application/x-httpd-php{/stala}. Możemy również dodać definicję, która z góry narzuci zasadę, aby wszystkie pliki były odczytywane na przykład jako html:

 

ForceType text/html

Jak widać, przy użyciu ForceType w prosty i znacznie szybszy sposób niż mod_rewrite można operować przyjaznymi linkami i rozszerzeniami.

Inne opcje

Prostą, ale dosyć istotną dyrektywą jest Indexes. Polega ona na zezwoleniu lub uniemożliwieniu przeglądania zawartości katalogów. Dla właścicieli stron lepiej by było, aby odwiedzający nie mieli możliwości swobodnego przeglądania zawartości katalogów. W tym celu do pliku .htaccess należy dopisać:

Options -Indexes

Jeśli dowolny użytkownik chciałby przejrzeć katalogi z poziomu przeglądarki, zobaczy komunikat: „403 dostęp zabroniony”. Gdy jednak zajdzie potrzeba udostępnienia zawartości katalogów, wówczas wpis powinien wyglądać następująco:

Options +Indexes

Jak widać, w miejsce minusa wystarczy wstawić plus.

Można również zezwolić na przeglądanie zawartości katalogów, ale z pewnymi ograniczeniami. W tym celu należy zastosować dyrektywę IndexIgnore, wymieniając rozszerzenia i ewentualne nazwy plików, których nie chcemy udostępniać:

Options +Indexes
IndexIgnore *gif *jpg *.png .?* g*

Powyższy zapis spowoduje, że podczas oglądania danego katalogu nie będą widoczne pliki graficzne (GIF, JPG, PNG), jak również te zaczynające się od kropki (np. .htaccess) oraz na literę \”g\”.

Eksperymentuj do woli To prawda, że plik .htaccess oferuje ogromne możliwości. Udowodniliśmy jednak, że do ich opanowania nie jest wymagana żadna wiedza tajemna. Wystarczy znajomość kilku podstawowych reguł i metaznaków, aby móc swobodnie zarządzać funkcjonowaniem adresów w serwisie internetowym. Jeżeli zaciekawił cię ten temat, zachęcamy do lektury pełnej dokumentacji serwera Apache (więcej na ten temat przeczytasz w ramce) i samodzielnego eksperymentowania z ustawieniami pliku .htaccess!

Hasła

Za pomocą pliku .htaccess można także ograniczyć dostęp do strony bądź danego katalogu tylko dla użytkowników, którzy będą znali login i hasło. Aby ustawić loginy użytkowników i ich hasła, należy najpierw stworzyć plik .htpasswd. Wpisujemy w nim niezakodowany login, po nim znak dwukropka, a następnie zakodowane hasło. To bardzo ważne, hasło musi być zakodowane zgodnie z algorytmem MD5.

Przykładowy plik .htpasswd powinien wyglądać następująco:

uzytkownik:zdSVMujsXokkE

Można stworzyć kilka loginów i haseł. Należy jednak pamiętać, aby każdy wpis zaczynał się od nowej linii. Dla przykładu:

uzytkownik1:jf05LdXAvmanY
uzytkownik2:5z0GcRGJ.CitM
uzytkownik3:rhGPWeaHukQb

Mamy już stworzony plik .htpasswd, teraz czas na odpowiedni zapis w pliku .htaccess:

AuthName \"Strefa zaszyfrowana\"
AuthType Basic
AuthUserFile /home/users/nazwakonta/public_html/joomla/.htpasswd
AuthGroupFile /dev/null
require valid-user

Linia AuthName odpowiada za nazwę zaszyfrowanego obszaru – ta nazwa będzie widoczna w okienku przy podawaniu loginu i hasła. Wartości AuthType i AuthGroupFile pozostają bez zmian, natomiast AuthUserFile powinno kierować do adresu, pod którym znajduje się plik .htpasswd, np.:

AuthUserFile /home/users/nazwakonta/public_html/joomla/.htpasswd

Ostatnia linia, czyli require valid-user, odpowiada za chroniony obszar. Jeśli cała strona ma być dostępna dopiero po wpisaniu hasła, wówczas pozostaje bez zmian, czyli:

require valid-user

Jeżeli jednak zamierzasz zabezpieczyć poszczególne pliki, wpis powinien zawierać dwie kolejne linie:

require valid-user

Czyli cały zapis będzie następujący:

AuthName \"Strefa zaszyfrowana\"
AuthType Basic
AuthUserFile /home/users/nazwakonta/public_html/joomla/.htpasswd
AuthGroupFile /dev/null

require valid-user

Zabezpieczając stronę hasłem, musimy pamiętać, że zadziała ono tylko wówczas, gdy użytkownik będzie korzystał z protokołu HTTP. Jeśli zdarzy się, że użyje połaczenia FTP, to takie zabezpieczenie nie będzie skuteczne.

Strony błędów

Dzięki edycji pliku .htaccess można także stworzyć własne strony błędów. Kody odpowiedzi HTTP są numerycznymi danymi wysyłanymi przez serwer do klienta. Kody informacyjne to 1XX, kody powodzenia to 2XX (np. kod 200), kody przekierowania zaczynają się od cyfry 3XX. My natomiast zajmiemy się kodami 4XX i 5XX – pierwsze są odpowiedzią błędu aplikacji po stronie użytkownika, drugie błędu serwera.

Na początek warto przypomnieć komunikaty błędów – patrz lista 1.

Lista 1. Komunikaty błędów (kod znaczenie):

  • 400 Błędne zapytanie
  • 401 Dostęp wymaga autoryzacji (np. hasło)
  • 402 Wymagana opłata (obecnie niestosowane)
  • 403 Zabroniony dostęp ze względu bezpieczeństwa
  • 404 Nie znaleziono strony, najpopularniejszy komunikat
  • 405 Niedozwolona metoda
  • 406 Nie może zwrócić odpowiedzi
  • 407 Wymagane uwierzytelnienie do serwera (podobne działanie jak 401)
  • 408 Koniec czasu oczekiwania na zapytanie
  • 409 Występowanie konfliktu między statusami zasobu
  • 410 Usunięto zasób
  • 411 Serwer odmawia realizacji ze względu na brak długości
  • 412 Jeden z warunków jest nie do spełnienia
  • 413 Zapytanie zbyt długie dla serwera
  • 414 Adres URL za długi
  • 415 Niezrozumiały komunikat dla serwera
  • 416 Nie można obsłużyć zakresu zapytania
  • 417 Oczekiwana wartość nie do zwrócenia
  • 500 Wewnętrzny błąd serwera
  • 501 Serwer nie może zwrócić odpowiedzi, ponieważ nie rozumie zapytania
  • 502 Błąd bramy, niepoprawna odpowiedź od serwera nadrzędnego
  • 503 Niedostępny, w danej chwili serwer jest przeciążony
  • 504 Przekroczony czas bramy (brak odpowiedzi od nadrzędnego)
  • 505 Nie obsługuje danej wersji HTTP

Definicja, którą należy wstawić do pliku .htaccess, aby zamienić standardową stronę błędu na nową, ogranicza się do jednej linii:

ErrorDocument 404 /errors/404.html

Ewentualnie można podać adres bezwzględny do pliku lub dokonać przekierowania na inną stronę:

ErrorDocument 404 http://www.magazynyinternetowe.pl

Jeśli nie chcesz tworzyć całej strony błędu, możesz również skorzystać z prostszego rozwiązania, czyli zdefiniować własny komunikat błędu. W tym celu należy zapisać:

ErrorDocument 404 \"Brak dokumentu na serwerze - przepraszamy\"

Podsumowując, standardowe strony błędów możemy zastąpić na kilka sposobów:

ErrorDocument 401 /errors/401.html
ErrorDocument 403 http://www.magazynyinternetowe.pl
ErrorDocument 404 \"Brak dokumentu na serwerze - przepraszamy\"

Blokowanie dostępu Ograniczenie dostępu do strony poprzez zastosowanie .htpassw to tylko jedna z możliwych metod. Możemy również blokować dostęp poszczególnym adresom IP lub ich całym grupom.

Może się to okazać przydatne przy różnego rodzaju ankietach lub przy kontrolowaniu działalności robotów internetowych.

Przykładowa konstrukcja zapisu powodująca zablokowanie dostępu z danego IP wygląda następująco:

deny from 123.456.789.000

W sytuacji, gdy chcemy zablokować dostęp wszystkim, na przykład do konkretnego katalogu, wystarczy wpisać:

deny from all

Można również zablokować dostęp wszystkim, poza wybranymi adresami. Wtedy zapis będzie następujący:

deny from all
allow from 123.456.789.000

W tym przepadku pierwsza linia odpowiada za całkowite zablokowanie dostępu, a druga umożliwia dostęp z adresu 123.456.789.000. Istnieje również możliwość zablokowania dostępu całym grupom adresów. Warto pamiętać o parametrze order, za pomocą którego nadajemy kolejność przetwarzania wpisów:

Order allow, deny

Powyższy zapis oznacza, że wpierw wykonywane są warunki allow, czyli odpowiadające za dostęp, a dopiero potem te ograniczające czyli deny. Przykładowy zapis z użyciem parametru

order wygląda następująco:
order allow, deny
deny from 123.456.789
deny from 000.123.4
allow from all

Gdyby w powyższym fragmencie kodu nie było zapisu order allow, deny, fragment allow from all osłabiłby działanie wcześniejszych. A tak, mimo umieszczenia na końcu, dyrektywa zostanie wypełniona zgodnie z oczekiwaniami (brak dostępu dla wyszczególnionych adresów IP i brak ograniczeń dla reszty).

Dostęp można również zablokować dla poszczególnych hostów z konkretnej subdomeny lub całych domen. Wtedy zapis będzie podobny do poprzednich:

order allow, deny
deny cos.domena.com
deny domena.com
allow from all

Moduł mod_rewrite jest dosyć popularny i niejednokrotnie okaże się przydatny. Warto upomnieć się o niego, jeśli z jakichś przyczyn został wyłączony przez administratora.
Bazuje on na definicjach wyrażeń regularnych zgodnych z PCRE (Perl Compatible Regular Expression).

Lista 2 przypominamy zastosowania podstawowych meta-znaków.

Lista 2. Metaznaki stosowane w wyrażenia regularnych symbol znaczenie

  • . Dowolny znak
  • ^ Oznacza początek napisu
  • $ Oznacznik końca (c$ znaczy, że ciąg tekstowy musi zakończyć się na c)
  • + Wystąpi jeden lub więcej razy
  • * Zero lub więcej wystąpień
  • ? Zero lub jedno wystąpienie
  • ! Negacja wyrażenia
  • ( Rozpoczyna grupowanie (przetwarzanie ciągu znaków, jakby był to pojedynczy element)
  • [ Rozpoczyna klasę znaków, np. dopasowane do przedziału od 0 do 9, to definicja klasy [0-9]

Nasz przykład rozpoczniemy od najprostszego przepisania adresu. Poniższy zapis sprawi, że do pliku index.php będzie można się odwołać, wpisując adres standardowego pliku index.html:

Options FollowSymLinks
RewriteEngine On
RewriteRule ^index\.html$ index.php [L]

Dwie pierwsze linie powodują aktywację mod-rewrite. Natomiast atrybut {stala}[L]{/stala} (od last rule) określa daną linię jako ostatnią, co oznacza, że reguły nie będą dalej wykonywane.

Możemy również dodać atrybut {stala}[NC]{/stala}, który sprawi, że bez względu na to, czy adres wpisywany jest wielkimi, czy małymi literami, będzie odczytany poprawnie. Dzięki temu {stala}IMAGES/2.jpg{/stala} będzie działać tak samo jak {stala}images/2.jpg{s/tala}.

Opis pozostałych atrybutów znajdziesz w ramce.

W zapisie pojawiają się jeszcze znaki {stala}^ i ${/stala}, będące tzw. metaznakami stosowanymi w wyrażeniach regularnych. Oznaczają one początek i koniec ciągu, po którym znajduje się wyraz index.html.

Sposób na meta-znaki

Symbole \\ . [ ^ $ | ( ) * + ? { to znaki o specjalnym znaczeniu, stosowane w wyrażeniach regularnych. Jeżeli potrzebujesz ich użyć jako zwykłych znaków, bez ich funkcji, poprzedź je backslashem \\.

Przyjazne linki

Przyjazne linki nie tylko poprawią skuteczność wyszukiwania naszych podstron przez boty wyszukiwarek, ale także ułatwiają korzystanie z serwisu użytkownikom.

Najprostsza zamiana linków występuje w przypadku, gdy mamy jedną zmienną. Adres

{stala}www.strona.pl/artykul.php?id=2{/stala}

będzie bardziej czytelny dla użytkownika i wyszukiwarki, gdy będzie następujący: {stala}www.strona.pl/artykul-2.html{/stala}. Aby tego dokonać, w pliku .htaccess wpisujemy:

RewriteRule ^artykul-([^-]+).html$artykul.php?id=

{stala}([^-]+){/stala} oznacza dowolny ciąg znaków złożony z przynajmniej jednego znaku bez myślnika (odpowiada za to zapis {stala}[^-]{/stala}, czyli każdy znak poza myślnikiem; gdyby nie symbol ^, temu zapisowi odpowiadałby tylko znak myślnika). Można go również zastąpić {stala}([0-9]+) lub (.*)){/stala}. Taki ciąg przenoszony jest do drugiej części reguły w miejsce $1.
Oczywiście fragment .html może zostać pominięty lub zastąpiony skrótem .htm – w zależności od potrzeb.

W regułach RewriteRule przed zmiennymi stoi znak $. Warto to zapamiętać, bo w regule Rewrite-Cond są one zapisywane ze znakiem procent %.

Podobnie będzie wyglądać sytuacja w przypadku kilku zmiennych w adresie. Dla przykładu jeden z artykułów na stronie opartej o CMS Joomla! wygląda następująco:

http://www/strona.pl/index.php?option=com_content&task=view&id=1&Itemid=26

Jest on długi i mało czytelny. Dlatego skorzystamy z następującego zapisu:

RewriteRule ([^-]+)/([^-]+)/([^-]+)/([^-]+)\.html$ index.php?option=&task=&id=&Itemid= [L]

Zapis ten bazuje na schemacie:

AllowOverride None

Stary adres w naszym przypadku miał 4 zmienne:

{stala}zmienna1=com_content&zmienna2_vie-w&zmienna3=1$zmienna4=26{/stala}

i zgodnie z tym zapisaliśmy stary adres, gdzie {stala}[^-]{/stala} oznacza ciąg znaków bez myślnika. Moglibyśmy również skorzystać z alternatywnego zapisu:

RewriteRule (com_content)/(view)/([^-]+)/([^-]+)\.html$ index.php?option=&task=&id=&Itemid= [L]

Bez względu na to, który zapis zastosujemy, nowy link będzie następujący:

{stala}http://www.strona.pl/com_content/view/1/26.html{/stala}

Należy pamiętać, że slash (/) można zamienić na przykład na myślniki, przecinki lub zapisać bez spacji. Poniżej prezentujemy zapis dla adresu składającego się z 5 zmiennych:

http://www.strona.pl/index.php?option=com_content&task=category&sectionid=1&id=1&Itemid=2

z użyciem kilku omówionych sposobów zapisu:

RewriteRule ([^-]+)/(category)/([^-]+)-(.*)([0-9]+)$ index.php?option=&task=&sectionid=&id=&Itemid= [L]

Tak zdefiniowany odnośnik będzie prezentował się w sposób następujący:

http://www.strona.pl/com_content/category/1-12

Jeszcze jedną przydatną opcją przy tworzeniu przyjaznych URL-i może okazać się usuwanie identyfikatorów sesji. Jeśli system, z którego korzystasz, dodaje ciąg znaków sesji, tzw. „sid”, warto go ukryć. W innym przypadku nasze starania nad stworzeniem czystych linków okażą się niemiarodajne, ponieważ link będzie posiadał atrybut sesji np.:

{stala}www.strona.pl/index.php?sid=12d34g567nn890123456789098w76547.{/stala}

W celu jego ukrycia, do pliku .htaccess należy dopisać:

#po linijce Options FollowSymLinks
php_flag session.use_trans_sid off

Przekierowania

Nie każdy zdaje sobie sprawę, że adresy {stala}http://www.strona.pl/{/stala} i {stala}http://strona.pl/{/stala} to z punktu widzenia wyszukiwarek dwa odrębne serwisy. Dlatego, aby uniknąć podpadnięcia duplicate content (czyli duplikowania treści, na co np. Google zwraca dużą uwagę), warto wybrać jeden z adresów, a drugi przekierować.

Przekierowanie z WWW na adres bez WWW:

RewriteCond %{HTTP_HOST} ^www.strona.com [NC]
RewriteRule ^(.*)$ http://strona.com/ [R=301,L]

Przekierowanie bez WWW na WWW:

RewriteCond %{HTTP_HOST} ^strona.com [NC]
RewriteRule ^(.*)$ http://www.strona.com/ [R=301,L]

Atrybut [NC] sprawia, że nie ma znaczenia wielkość użytych liter we wpisywanym adresie.

Identycznie należy postąpić w sytuacji, gdy ze starego adresu strony chcemy w bezpieczny sposób przekierować ruch na nowy. Wtedy zapis będzie następujący:

RewriteCond %{HTTP_HOST} ^stary_adres.com [NC, OR]
RewriteCond %{HTTP_HOST} ^www.stary_adres.com
RewriteRule ^(.*)$ http://www.nowy.com/ [R=301,L]

Za pomocą RewriteCond możemy również sprawdzić, czy adres nie prowadzi do pliku bądź katalogu:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteuRule .* index.html [L]

Pierwsza linia sprawdza, czy ścieżka nie prowadzi do pliku, druga sprawdza to samo pod kątem katalogu. Kod w trzeciej linii określa, że jeśli żaden plik nie zostanie odnaleziony (!-f), wówczas zostanie załadowany plik {stala}index.html{/stala}.

Flagi modułu mod_rewrite

  • [R = kod] force redirect – pozwala na przekierowanie linku według podanej wartości

  • [QSA] query string append – powoduje dodanie na końcu całego zapytania query string

  • [L] last rule – ustanawia linijkę jako ostatnią, reguły nie będą dalej wykonywane

  • [NC] no case – ignoruje fakt, czy adres wpisywany jest wielkimi, czy małymi literami

  • [T = MIME type] force MIME type – ustawienie typu MIME

  • [F] force URL to be forbidden – zwraca błąd 403

  • [S=liczba] skip next rule(s) – pomija zapisaną liczbę reguł

  • [N] next round – przetwarzanie od początku

Pozostałe flagi zostały szczegółowo opisane w dokumentacji modułu mod_rewrite, dostępnej pod adresem http://httpd.apache.org/docs/2.2/mod/mod_rewrite.html

Nic nie stoi na przeszkodzie, aby dokonać też innych przekierowań. Załóżmy, że chcemy, aby internauta po kliknięciu na odnośniku http://www.strona.pl/informacje, zobaczył podstronę znajdującą się w innym katalogu, niż wskazywałby to adres. Najprościej będzie skorzystać z przekierowania:

Redirect /katalog http://www.strona.pl/plik.php

Zapis ten oznacza, że użytkownik wchodząc do katalogu {stala}http://www.strona.pl/informacje{/stala}, tak naprawdę zostanie przeniesiony na stronę {stala}http://www.strona.pl/plik.php{/stala}