Szablon pliku .htaccess
Info
Zamieszczony poniżej szablon nie zawiera adresu, pod jakim jest umieszczony. Można go zatem łatwo kopiować między projektami.
W związku z uwagami czytelników jestem winien pewne wyjaśnienie. Określenie "jak powinien wyglądać plik .htaccess" jest tu skrótem myślowym. Podany poniżej szablon należy traktować jako przykład pliku .htaccess dla statycznego bloga, który może być inspiracją do dalszych modyfikacji celem spełnienia specyficznych wymagań zależnych od konkretnego przypadku.
<IfModule mod_mime.c>
AddType application/vnd.ms-fontobject .eot
AddType application/x-font-ttf .ttf
AddType application/x-font-opentype .otf
AddType application/x-font-woff .woff
AddType application/font-woff2 .woff2
AddType image/svg+xml .svg
</Ifmodule>
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE application/javascript application/x-javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/x-icon \
image/svg+xml \
application/vnd.ms-fontobject \
application/x-font-ttf \
font/opentype \
application/x-font-woff \
application/font-woff2
</Ifmodule>
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/html "access 5 minutes"
ExpiresByType text/css "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType application/pdf "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType application/x-font-ttf "access plus 1 year"
ExpiresByType application/x-font-opentype "access plus 1 year"
ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
</IfModule>
<IfModule mod_headers.c>
Header set Content-Security-Policy " \
default-src 'self';\
script-src 'self' 'unsafe-inline' https://www.google-analytics.com https://cdnjs.cloudflare.com https://maxcdn.bootstrapcdn.com https://www.googletagmanager.com *.disqus.com disqus.com *.disquscdn.com; \
object-src 'none'; \
frame-src https://disqus.com https://www.youtube.com; \
img-src 'self' https://*.disqus.com https://*.disquscdn.com *.google-analytics.com https://cdn.viglink.com https://*.doubleclick.net; \
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://stackpath.bootstrapcdn.com https://cdn.jsdelivr.net https://c.disquscdn.com; \
connect-src 'self' https://api.robertolechowski.com *.disqus.com; \
font-src https://fonts.googleapis.com https://fonts.gstatic.com https://stackpath.bootstrapcdn.com https://cdn.jsdelivr.net; \
base-uri 'self'"
Header always set X-Content-Type-Options "nosniff"
Header set Set-Cookie HttpOnly;Secure
Header always set X-FRAME-OPTIONS "DENY"
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header set Referrer-Policy "origin-when-cross-origin"
Header set Feature-Policy: "microphone 'none'; \
camera 'none'; \
payment 'none'; \
geolocation 'self'"
</IfModule>
AddDefaultCharset UTF-8
RewriteEngine On
ErrorDocument 401 https://%{SERVER_NAME}/404
ErrorDocument 404 https://%{SERVER_NAME}/404
ErrorDocument 500 https://%{SERVER_NAME}/404
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R=301,L]
RewriteRule ^index\.html$ / [R=301,L]
RewriteRule ^(.*)/index\.html$ /$1/ [R=301,L]
ServerSignature Off
Jak to działa? – wyjaśnienie działania
Definiujemy typy zasobów
Definiujemy typy nowe zasobów na podstawie rozszerzenia pliku.
<IfModule mod_mime.c>
AddType application/vnd.ms-fontobject .eot
AddType application/x-font-ttf .ttf
AddType application/x-font-opentype .otf
AddType application/x-font-woff .woff
AddType application/font-woff2 .woff2
AddType image/svg+xml .svg
</Ifmodule>
Definiujemy kompresje
Ustalamy domyślny typ kompresji dla wybranych typów zasobów.
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/css application/json
AddOutputFilterByType DEFLATE application/javascript application/x-javascript
AddOutputFilterByType DEFLATE text/xml application/xml text/x-component
AddOutputFilterByType DEFLATE application/xhtml+xml application/rss+xml application/atom+xml
AddOutputFilterByType DEFLATE image/x-icon \
image/svg+xml \
application/vnd.ms-fontobject \
application/x-font-ttf \
font/opentype \
application/x-font-woff \
application/font-woff2
</Ifmodule>
Konfiguracja czasu życia
Należy ustalić, jak długo zezwalamy przeglądarce przechowywać zasoby bez ich ponownego pobierania.
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType text/html "access 5 minutes"
ExpiresByType text/css "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
ExpiresByType application/pdf "access plus 1 year"
ExpiresByType application/x-javascript "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType application/vnd.ms-fontobject "access plus 1 year"
ExpiresByType application/x-font-ttf "access plus 1 year"
ExpiresByType application/x-font-opentype "access plus 1 year"
ExpiresByType application/x-font-woff "access plus 1 year"
ExpiresByType application/font-woff2 "access plus 1 year"
</IfModule>
Ustawienie Content - Security - Policy (opens new window)
Dokonujemy zdefiniowania Content - Security - Policy (opens new window). Czynimy to osobno dla różnych typów zasobów.
Header set Content-Security-Policy " \
default-src 'self' https://*.disqus.com https://c.disquscdn.com\;
script-src 'self' 'unsafe-inline' https://www.google-analytics.com https://cdnjs.cloudflare.com https://maxcdn.bootstrapcdn.com https://www.googletagmanager.com; \
object-src 'none'; \
frame-src https://disqus.com https://www.youtube.com; \
img-src 'self'; \
style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://stackpath.bootstrapcdn.com https://cdn.jsdelivr.net; \
connect-src 'self' https://*.disqus.com; \
font-src https://fonts.googleapis.com https://fonts.gstatic.com https://stackpath.bootstrapcdn.com https://cdn.jsdelivr.net; \
base-uri 'self'"
Nagłówki związane z bezpieczeństwem
Przeglądarka nie będzie 'zgadywać' typu MIME zasobu na podstawie zawartości. (link (opens new window))
Header always set X-Content-Type-Options "nosniff"
Zablokowanie dostępności ciasteczek z poziomu JavaScript. (link (opens new window))
Header set Set-Cookie HttpOnly;Secure
Zablokowanie wyświetlania naszej strony w ramkach. (link (opens new window))
Header always set X-FRAME-OPTIONS "DENY"
Utrudnienie potencjalnych ataków XSS (link (opens new window))
Header always set X-XSS-Protection "1; mode=block"
Poinformowanie klienta, że prezentowana witryna powinna być dostępna wyłącznie przez https. (link (opens new window))
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Zdefiniowanie informacji, które będą przekazywane do obcych serwerów w nagłówku Referer (opens new window). (link (opens new window))
Header set Referrer-Policy "origin-when-cross-origin"
Wyłączenie wybranego API przeglądarki dla danej witryny (link (opens new window))
Header set Feature-Policy: "vibrate 'none'; \
notifications 'none'; \
push 'none'; \
microphone 'none'; \
camera 'none'; \
payment 'none'; \
geolocation 'self'"
Przekierowania
Strony błędów
ErrorDocument 401 https://%{SERVER_NAME}/404
ErrorDocument 404 https://%{SERVER_NAME}/404
ErrorDocument 500 https://%{SERVER_NAME}/404
Przekierowanie do adresu bez www
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^ %{REQUEST_SCHEME}://%1%{REQUEST_URI} [R=301,L]
Przekierowanie do protokołu https
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{SERVER_NAME}/$1 [R=301,L]
Wyeliminowanie wyświetlania '.html' na końcu nazwy danego zasobu
RewriteRule ^index\.html$ / [R=301,L]
RewriteRule ^(.*)/index\.html$ /$1/ [R=301,L]