1   2   3   4   5   6   7   8 

Obsługa błędów 404 Not Found w Apache/PHP. Przewodnik

8. Przykład praktyczny

Jako przykład praktyczny przeanalizujmy dwie witryny WWW. Jedna z nich będzie stosowała zwykłe adresy URL, a druga — adresy przyjazne. Witryny te są tak wykonane, by mogły zostać umieszczone na serwerze udostępnianym przez zewnętrzną firmę. Zakładamy, że:

8.1 Przykładowa witryna Lorem ipsum

Wygląd witryny jest przedstawiony na rysunku 7. Jest ona wykonana w PHP przy wykorzystaniu szablonów Smarty i plików tekstowych. Poziome menu witryny powstaje na podstawie pliku tekstowego dane/menu.txt o zawartości:

Lorem|lorem.txt|2
Ipsum|ipsum.txt|3
Dolor|dolor.txt|4
Sit amet|sit-amet.txt|5

Każda linijka pliku opisuje jedną opcję. Kolejne kolumny to:

Cała witryna stosuje następujące adresy URL:

index.php?id=1 - strona błędu 404
index.php?id=2 - strona lorem
index.php?id=3 - strona ipsum
index.php?id=4 - strona dolor
index.php?id=5 - strona sit amet
img/*.png      - obrazy użyte na stronie
style.css      - style strony

Dodatkowo adres index.php jest przekierowaniem do strony domyślnej lorem o adresie index.php?id=2.

Rysunek 7. Przykładowa witryna

Witryna składa się z plików i folderów przedstawionych na rysunku 8. W ramach usługi WWW dostępnymi plikami powinny być wyłącznie:

index.php
style.css
img/*.png

żadne pliki z folderów:

dane/
include/
template/
template_c/

nie powinny być dostępne poprzez WWW.

Rysunek 8. Pliki i foldery omawianego przykładu

8.2 Rozwiązanie pierwsze: witryna bez przyjaznych URL-i

W przypadku witryny, która nie stosuje przyjaznych adresów URL w pliku .htaccess umieszczamy następujące dyrektywy:

Do ustalenia strony domyślnej stosujemy dyrektywy Options oraz DirectoryIndex:

Options -Indexes
DirectoryIndex index.php

Pierwsza z nich wyłącza możliwość listowania zawartości katalogu, a druga ustala, że adres kończący się nazwą folderu, np.

http://localhost/przyklad/

będzie odwoływał się do pliku:

http://localhost/przyklad/index.php

Następnie ustalamy strony błędów:

ErrorDocument 404 /index.php?id=1
ErrorDocument 403 /index.php?id=1

pamiętając o tym, by w skrypcie index.php użyć funkcji header() do generowania nagłówka Not found:

if ($akcja == 1) {
    header('HTTP/1.x 404 Not Found');    
} else {
    ...
}

Na zakończenie blokujemy dostęp do wszystkich plików:

<Files ~ ".*$">
    Order allow,deny
    Deny from all
</Files>

po czym odblokowujemy dostęp do plików index.php, .css, .png oraz do folderu:

<Files ~ "index\.php$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.css$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.png$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "^$">
    Order allow,deny
    Allow from all
</Files>

Pełna zawartość pliku .htaccess jest przedstawiona na listingu 1.

Options -Indexes

DirectoryIndex index.php

ErrorDocument 404 /index.php?id=1
ErrorDocument 403 /index.php?id=1

<Files ~ ".*$">
    Order allow,deny
    Deny from all
</Files>

<Files ~ "index\.php$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.css$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.png$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "^$">
    Order allow,deny
    Allow from all
</Files>

Listing 1. Plik .htaccess rozwiązania bez przyjaznych adresów URL

8.3 Rozwiązanie drugie: witryna z przyjaznymi adresami URL-i

Przypadek, w którym witryna stosuje przyjazne adresy URL jest nieco bardziej skomplikowany. Tym razem stosujemy adresy .html, które będą przekierowane na skrypty PHP:

error.html       ->  index.php?id=1
lorem.html       ->  index.php?id=2
ipsum.html       ->  index.php?id=3
dolor.html       ->  index.php?id=4
sit-amet.html    ->  index.php?id=5

Podobnie jak poprzednio, plik .htaccess rozpoczynamy od ustalenia strony domyślnej:

Options -Indexes
DirectoryIndex index.php

Następnie dołączamy dyrektywy odpowiedzialne za translacje adresów:

RewriteEngine on
RewriteRule ^error\.html$       index.php?id=1
RewriteRule ^lorem\.html$       index.php?id=2
RewriteRule ^ipsum\.html$       index.php?id=3
RewriteRule ^dolor\.html$       index.php?id=4
RewriteRule ^sit-amet\.html$    index.php?id=5

Po czym ustalamy strony błędów:

ErrorDocument 404 /error.html
ErrorDocument 403 /error.html

i blokujemy dostęp do plików:

<Files ~ ".*$">
    Order allow,deny
    Deny from all
</Files>

<Files ~ "index\.php$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.html$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.css$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.png$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "^$">
    Order allow,deny
    Allow from all
</Files>

Kompletny plik .htaccess jest przedstawiony na listingu 2.

Options -Indexes
DirectoryIndex index.php

RewriteEngine on

RewriteRule ^error\.html$               index.php?id=1
RewriteRule ^lorem\.html$               index.php?id=2
RewriteRule ^ipsum\.html$               index.php?id=3
RewriteRule ^dolor\.html$               index.php?id=4
RewriteRule ^sit-amet\.html$            index.php?id=5

ErrorDocument 404 /error.html
ErrorDocument 403 /error.html

<Files ~ ".*$">
    Order allow,deny
    Deny from all
</Files>

<Files ~ "index\.php$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.html$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.css$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "\.png$">
    Order allow,deny
    Allow from all
</Files>

<Files ~ "^$">
    Order allow,deny
    Allow from all
</Files>

Listing 2. Plik .htaccess rozwiązania stosującego przyjazne URL-e

W kodzie skryptu PHP możemy dodatkowo zablokować dostęp do witryny adresami index.php:

if (preg_match('/index\.php/', $_SERVER['REQUEST_URI'])) {
    header('Location: http://localhost/lorem.html');
    header('HTTP/1.x 301 Moved Permanently');
}

Dzięki temu odwołania do stron:

index.php
index.php?id=2
index.php?id=3
...

będą przekierowywane na stronę główną.

Uwaga

Ponieważ przykładowe witryny stosują adresy bezwzględne:

/style.css
/lorem.html
/img/logo.png
...

przykłady należy uruchamiać w folderze głównym serwera.

 1   2   3   4   5   6   7   8