Полное руководство по mod_rewrite (часть 5): Частые случаи и примеры использования mod_rewrite

Оглавление. Полное руководство по mod_rewrite

1. Как включить и как работает mod_rewrite

2. Регулярные выражения mod_rewrite

3. Флаги RewriteRule

4. Директива RewriteCond

5. Частые случаи и примеры использования mod_rewrite

5.1 Проверка доступности mod_rewrite

5.1.1 Как включить RewriteEngine

5.1.2 Как проверить, включён ли mod_rewrite

5.1.3 Как сделать так, чтобы правила перезаписи использовались только если mod_rewrite включен

5.2 Использование mod_rewrite для перенаправления (редиректа) и переназначения URL

5.2.1 Страница поменяла адрес, как показать новую страницу по старому адресу без редиректа

5.2.2 Страница поменяла адрес, как перенаправить на новую страницу при запросе старой (редирект)

5.2.3 Переадресация при смене домена

5.2.4 Простой редирект на новый сайт

5.2.5 Как переправить все запросы из одной директории, в другую

5.2.6 Использовать URL адресов без расширения файлов .php

5.2.7 Универсальный документ ошибки (Error Document) для не найденных ресурсов (ошибка 404 Not Found)

5.2.8 Со статики на динамику

5.2.9 Обратная совместимость для изменений расширения файла

5.2.10 Замена на WebP изображения

5.3 Канонические имена хостов и URL. HTTPS

5.3.1 Как сделать редирект с HTTP на HTTPS

5.3.2 Как сделать редирект на с HTTP на HTTPS всех страниц кроме некоторых

5.3.3 Как сделать редирект на с HTTP на HTTPS только некоторых страниц

5.3.4 Принудительное использование HTTPS за прокси

5.3.5 Всегда использовать WWW перед именем домена

5.3.6 Всегда использовать WWW перед именем домена – универсальный вариант

5.3.7 Никогда не использовать WWW перед именем домена

5.3.8 Никогда не использовать WWW перед именем домена – универсальный вариант

5.3.9 Принудительное использование канонического имени с HTTPS и www

5.3.10 Канонический вид с HTTPS и без www

5.3.11 Принудительное SSL и www для главного домена, принудительное SSL без www для всех поддоменов (кроме локальных)

5.3.12 Принудительное добавление конечного слеша к адресу сайта

5.3.13 Удаление конечного слеша

5.3.14 Удаление лишних слешей в адресе URL

5.4 Контроль доступа и блокировка хотлинка

5.4.1 Ограничение доступа по IP

5.4.2 Запрет доступа к скрытым файлам и директориям

5.4.3 Запрет хотлинка изображений

5.4.4 Запрет хотлинкинга только для определённых доменов

5.4.5 Разрешение хотлинка для определённых сайтов

5.4.6 Блокировка пользователя по рефереру (Referrer)

5.4.7 Блокировка плохих ботов, клонеров сайтов, офлайн браузеров

5.4.8 Запрет доступа к файлу или директории в определённые периоды времени

6. Продвинутые техники

7. Директива RewriteMap

8. Директива RewriteOptions, технические подробности, когда НЕ использовать mod_rewrite


В предыдущих частях мы изучили практически всю документацию по mod_rewrite. Остались директивы RewriteMap и RewriteOptions. RewriteMap также используется для перезаписи URL адресов, но применяется реже других; к ней мы вернёмся позже. Директива RewriteOptions также применяется нечасто. Особенностью RewriteMap является то, что её нельзя использовать в .htaccess. Её можно использовать только в контексте сервера, либо виртуальных хостов. По большому счёту, RewriteMap не добавляет новой функциональности – она только позволяет вынести большой массив данных, которые нецелесообразно или слишком сложно описывать при помощи регулярных выражений, в отдельные файлы. Получаются такие выделенные базы данных. Тем не менее, мы всё равно рассмотрим RewriteMap в одной из последующих частей.

Сейчас для закрепления изученной теории, мы перейдём к практическим примерам самых частых случаев использования mod_rewrite, включая подробное описание того, как они работаю. Если после знакомства с теорией и этими примерами у вас остались вопросы, то пишите их здесь в комментариях.

Обратите внимание, что во многих примерах используются конкретные файловые пути, значения запросов и прочее – эти примеры не будут работать у вас без изменений в вашей конфигурации сервера, поэтому важно, чтобы вы их понимали, а не просто копировали в вашу конфигурацию.

Проверка доступности mod_rewrite

Как включить RewriteEngine

О включении модуля mod_rewrite в конфигурационном файле Apache было рассказано в первой части. Если модуль включен, то его необходимо активировать в файле .htaccess директивой RewriteEngine:

RewriteEngine On

Это достаточно сделать один раз, даже если вы используете несколько правил перезаписи.

Для работы модуля также необходима активация опции FollowSymLinks. Эта опция может быть активирована в конфигурационном файле Apache (об этом также уже было сказано в первой части). Если эта опция отключена на уровне веб-сервера (или виртуального хоста), то её можно включить в файле .htaccess. Её нужно указать до директивы RewriteEngine:

Options +FollowSymLinks
RewriteEngine On

Как проверить, включён ли mod_rewrite

Как проверить в PHP включён mod_rewrite или нет

Самым простым способом является использование функции phpinfo(). Если модуль включён, то в таблице apache2handler в колонке Loaded Modules будет указано mod_rewrite (а также все другие модули, которые включены).

Этот способ является самым универсальным: вы можете использовать его в любой системе, в том числе на совместном (shared) хостинге.

Как проверить в Windows включён ли mod_rewrite

Откройте командную строку (Win+x, затем выберите Windows PowerShell). Перейдите в каталог, где размещены бинарные файлы Apache. Например, в моём случае это папка C:\Server\bin\Apache24\bin\:

cd C:\Server\bin\Apache24\bin\

И выполните там команду:

./httpd.exe -M

Будет выведен полный список модулей.

Как проверить в Linux включён ли mod_rewrite

Чтобы вывести список всех загруженных веб-сервером Apache модулей, используется опция -M. Исполнимый файл веб-сервера может называться apache2ctl или httpd в зависимости от используемого дистрибутива.

Для Debian, Ubuntu, Kali Linux, Linux Mint и их производных команда для вывода списка модулей следующая:

apache2ctl -M

Для Arch Linux, BlackArch и некоторых других дистрибутивов команда такая:

httpd -M

Проверка включён ли mod_rewrite с помощью .htaccess

В файле .htaccess запишите директиву:

RewriteEngine on

И попробуйте открыть адрес папки, где вы сохранили .htaccess, если возникнет ошибка «500 Internal server error», значит модуль mod_rewrite не включён в конфигурационном файле Apache.

Как сделать так, чтобы правила перезаписи использовались только если mod_rewrite включен

Конструкция <IfModule> проверяет, включён ли модуль. Если модуль включён, то выполняются директивы, которые находятся в секции <IfModule>…</IfModule>. Если модуль отключён, то эти директивы игнорируются. В результате, если модуль выключен, то неизвестные директивы не вызовут ошибку веб-сервера.

Синтаксис использования:

<IfModule mod_rewrite.c>
……
……
</IfModule>

Вместо многоточий запишите желаемые директивы mod_rewrite, пример:

<IfModule mod_rewrite.c>
     RewriteEngine On
     RewriteCond %{HTTP_USER_AGENT} ^HTTrack [NC,OR]
     RewriteCond %{HTTP_USER_AGENT} ^sqlmap [NC,OR]
     RewriteCond %{HTTP_USER_AGENT} ^wpscan [NC,OR]
     RewriteCond %{HTTP_USER_AGENT} ^text [NC]
     RewriteRule ^.* - [F]
</IfModule>

Перед именем модуля можно поставить ! (восклицательных знак) и тогда то, что внутри IfModule будет выполнено только если проверяемый модуль НЕ включён.

Секции <IfModule> можно использовать внутри другой секции <IfModule> и выполнять простые тестирования нескольких модулей в зависимости от условия предыдущих тестов модулей.

Эту секцию следуют использовать только если вам нужен один конфигурационный файл, которые работает независимо от того, доступен ли определённый модуль. При обычной работе директивы не должны размещаться в секциях <IfModule>.

Использование mod_rewrite для перенаправления (редиректа) и переназначения URL

Страница поменяла адрес, как показать новую страницу по старому адресу без редиректа

Описание:

Предположим, мы недавно переименовали страницу foo.html в bar.html и теперь хотим, чтобы старый URL также работал для обратной совместимости. Однако мы хотим, чтобы пользователи старого URL-адреса даже не узнали, что страницы были переименованы, то есть мы не хотим, чтобы адрес изменялся в их браузере.

Решение:

Мы с помощью RewriteRule делаем преобразования запроса, содержащего старый адрес, на новый, задав следующее правило:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "/bar.html" [PT]

В этом примере ^/foo\.html$ является регулярным выражением. Символы ^ и $ обозначают начало и конец строки соответственно. Перед точкой стоит слеш, чтобы символ трактовался буквально (как точка), а не как подстановочный символ (в качестве подстановочного символа точка означает любой один символ).

Страница поменяла адрес, как перенаправить на новую страницу при запросе старой (редирект)

Описание:

Предположим еще раз, что мы недавно переименовали страницу foo.html в bar.html и вновь хотим, чтобы старый URL работал для обратной совместимости. Но на этот раз мы хотим, чтобы пользователи старого URL-адреса получили намек на новый, т. е. поле адресной строки их веб-браузера должно измениться.

Решение:

Мы принудительно перенаправляем HTTP на новый URL-адрес, что приводит к изменению адреса страницы в браузере и, следовательно, того, что показано пользователю:

RewriteEngine  on
RewriteRule    "^/foo\.html$"  "bar.html" [R]

Кстати, для простых случаев редиректа можно использовать директиву Redirect. Эта директива не смогла бы заменить первый пример, когда мы показываем содержимое другой страницы без смены адреса (без редиректа). С Redirect второй пример выглядел бы так:

Redirect "/foo.html" "/bar.html"

Переадресация при смене домена

Описание:

Если сайт сменил домен, но сохранил прежнюю структуру страниц. Вы хотите, чтобы старые URL адреса продолжали работать пока пользователи не обновят их закладки.

Решение:

Вы можете использовать mod_rewrite для перенаправления этих URL на новый домен, но также рассмотрите вариант с использованием директив Redirect или RedirectMatch.

В последующих примерах замените example.com на адрес сайта, куда должен выполняться редирект.

# С mod_rewrite
RewriteEngine on
RewriteRule   "^/docs/(.+)"  "http://new.example.com/docs/$1"  [R,L]

Правило означает найти запросы, которые содержат строку, которая начинается с /docs/ (символ ^ означает начало строки, а /docs/ — это буквальная последовательность символов), за которой затем следует что угодно (точка означает любой символ, а знак плюс означает один или более раз). Скобки образуют обратную ссылку. Т.е. то, что совпадает с выражением в скобках, можно использовать в дальнейшем, сославшись на это с помощью $1.

В строке перезаписи http://new.example.com/docs/ является буквальной частью, а $1 – это то, что совпало с частью выражения в скобках, т.е. обратная ссылка на (.+).

Таким образом, если был сделан запрос http://another.com/docs/best, то будет сделана переадресация на адрес http://new.example.com/docs/best.

# С RedirectMatch
RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1"
# С Redirect
Redirect "/docs/" "http://new.example.com/docs/"

Директивы Redirect и RedirectMatch должы быть «легче» для сервера, но не всегда сложные случаи можно описать без использования mod_rewrite.

Простой редирект на новый сайт

Если сайт сменил домен и не сохранил структуру страниц, т.е. если вам нужно перенаправить все запросы на новый сайт (например, на его главную страницу), то это делается так:

RewriteEngine  on
RewriteRule ^ https://newsite.ru

В результате независимо от запрошенной страницы, все запросы будут переданы на главную страницу другого домена. Замените https://newsite.ru на тот сайт, куда вы перенаправляете запросы.

Как переправить все запросы из одной директории, в другую

Псевдоним для единичной директории:

RewriteEngine On
RewriteRule ^source-directory/(.*) /target-directory/$1 [R=301,L]

Все обращения к содержимому директории source-directory будут переадресованы к содержимому директории target-directory.

Использовать URL адресов без расширения файлов .php

Этот снипет позволяет вам использовать URL без расширения PHP, например, example.com/users вместо example.com/users.php.

RewriteEngine On
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^([^.]+)$ $1.php [NC,L]

Универсальный документ ошибки (Error Document) для не найденных ресурсов (ошибка 404 Not Found)

Следующее правило выводит указанный вами файл в случае возникновения ошибки 404 Not Found. Обратите внимание, что вам самим нужно указать правильный код ответа HTTP 404 в заголовках ответа (в PHP коде, например).

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /dir/error.php [END]

Если это правило перезаписи вызовет ошибку сервера, то замените флаг [END] на [L]. Флаг [END] подходит лучше, но поддерживается Apache 2.4 и не поддерживается версией Apache 2.2.

Вместо /dir/error.php нужно указать путь до файла, который вы хотите показывать в случае возникновения ошибки 404 (файл не найден).

Со статики на динамику

Описание:

Как мы можем трансформировать статичную страницу foo.html в динамичный вариант foo.cgi бесшовным образом, т.е. без уведомления браузера/пользователя.

Решение:

Мы просто переписываем URL на CGI-скрипт и принуждаем обработчик быть cgi-скриптом так, что он выполняется как CGI программа. Таким образом, запрос /~quux/foo.html внутренне приводить к вызову /~quux/foo.cgi.

RewriteEngine  on
RewriteBase    "/~quux/"
RewriteRule    "^foo\.html$"  "foo.cgi"  [H=cgi-script]

Обратная совместимость для изменений расширения файла

Описание:

Как мы можем сделать обратную совместимость URL (виртуально ещё существующих) после миграции document.YYYY в document.XXXX, например, после перехода ряда.html файлов на .php?

Решение:

Мы переписываем имя в его базовое имя и проверяем наличие файла с новым расширением. Если он существует, мы берем его, иначе URL используется в исходном состоянии.

#   набор правил для обратной совместимости
#   для перезаписи document.html на document.php
#   только тогда, когда document.php существует
<Directory "/var/www/htdocs">
    RewriteEngine on
    RewriteBase "/var/www/htdocs"

    RewriteCond "$1.php" -f
    RewriteCond "$1.html" !-f
    RewriteRule "^(.*).html$" "$1.php"
</Directory>

Обсуждение

В этом примере используется часто забываемая возможность mod_rewrite, вытекающая из порядка выполнения набора правил. В частности, mod_rewrite оценивает левую сторону RewriteRule (Шаблон поиска), прежде чем оценивать директивы RewriteCond. Следовательно, $1 уже определён к тому времени, когда оцениваются директивы RewriteCond. Это позволяет нам проверять наличие исходного (document.html) и целевого (document.php) файла с использованием того же базового имени файла.

Этот набор правил предназначен для использования в контексте директорий (в блоке <Directory> или в файле .htaccess), так что проверки -f смотрят в каталог по правильному пути. Возможно, вам потребуется установить директиву RewriteBase, чтобы указать базу каталогов, в которой вы работаете.

Замена на WebP изображения

Если поддерживаются WebP изображения, и изображение с файловым расширением .webp найдено в том же месте, где на сервере находится картинка jpg/png, то вместо неё будет отправлено изображение WebP.

RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]

Канонические имена хостов и URL. HTTPS

К одной и той же странице можно обратиться по-разному. Например, главную страницу сайта можно открыть любым из следующих методов:

  • http://www.yoursite.com/
  • http://yoursite.com/
  • http://www.yoursite.com
  • http://yoursite.com
  • http://www.yoursite.com/index.php
  • http://yoursite.com/index.php
  • http://yoursite.com/?

Вариантов может быть даже больше, если сайт доступен и на HTTP, и на HTTPS. Также варианты могут возникнуть из-за различных ошибок составления ссылок, при которых страница продолжает открываться. Например:

  • http://www.yoursite.com//index.php

Хотя большинству людей понятно, что все эти URL являются одним и тем же, с технической точки зрения это не так. Для веб-сервера это различные URL. И если они открыты, поисковые системы их могут проиндексировать.

Поисковые системы стали значительно более продвинутыми, но не нужно рассчитывать только на них в вопросе борьбы с диблирующими страницами. К тому же, это может внести путаницу в аналитику (когда для каждого из перечисленного примера доход или посещаемостью считаются отдельно, хотя это одна и та же страница).

Поэтому веб-мастеру следует позаботиться о каноническом URL. На самом деле, нет никакой разницы, какую именно форму URL вы выберите в качестве канонической. Главное, выбрать что-то одно и придерживаться этого.

Как сделать редирект с HTTP на HTTPS

Помните, что для использования HTTPS протокола недостаточно просто сделать переадресацию, также должен быть настроен веб-сервер. То есть вы должны получить сертификаты и указать их в настройках хоста. Также веб-сервер должен быть настроен на прослушивание 443 порта. Если это всё готово, то для перенаправления на HTTPS, в файл .htaccess добавьте строки:

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}

В этом примере переменная %{HTTPS} содержит on, если сайт использует HTTPS и содержит off, если используется HTTP. Таким образом, адрес страницы переписывается только если к ней обращаются по HTTP.

В RewriteRule в качестве шаблона поиска используется ^ — символ начала строки. Т.е. под это условие подпадают все строки. Цель переадресации указывается с помощью буквальной строки https:// и двух переменных окружения %{HTTP_HOST} и %{REQUEST_URI}.

Также на вашем HTTPS веб-сайте рекомендуется включить HTTP Strict Transport Security (HSTS) для помощи в предотвращении атак человек-посередине. Для этого достаточно добавить строки:

<IfModule mod_headers.c>
    Strict-Transport-Security: max-age=31536000; includeSubDomains
</IfModule>

Подробности: https://developer.mozilla.org/en-US/docs/Web/Security/HTTP_strict_transport_security

Как сделать редирект на с HTTP на HTTPS всех страниц кроме некоторых

Предположим, что нам нужно перевести на HTTPS все страницы кроме тех, которые находятся в папке /.well-known/, тогда используется следующая конструкция:

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} !^/.well-known/
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}

Замените /.well-known/ на желаемую папку или адрес страницы.

Если нужно исключить несколько страниц или каталогов, то составьте регулярное выражение с альтернативным выбором, т.е. с использованием трубы (|). Например, нужно включить переадресацию на HTTPS для всех страниц кроме находящихся в папке /.well-known/, в папке /test/, а также файла /stay-away.php:

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} !^(/.well-known/|/test/|/stay-away.php)
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}

Как сделать редирект на с HTTP на HTTPS только некоторых страниц

Если вам нужно перенаправить с HTTP на HTTPS только отдельные страницы, то подойдут показанные ранее примеры. Единственное необходимое в них изменение – убрать восклицательный знак (!), который служит для отрицания совпадения.

Для настройки редиректа на HTTPS только для папки /.well-known/

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} ^/.well-known/
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}

Для настройки редиректа на HTTPS только для папки /.well-known/, папки /test/, а также файла /stay-away.php:

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} ^(/.well-known/|/test/|/stay-away.php)
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}

Принудительное использование HTTPS за прокси

Полезно, если у вас есть прокси-сервер перед вашим сервером, отключающий TLS.

RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

Всегда использовать WWW перед именем домена

Если вы хотите, чтобы в строке браузера перед названием домена всегда шло www, то используйте следующие правила:

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

Обратите внимание, что example.com нужно заменить на домен вашего сайта, вместо протокола http:// может быть указано https://, а в строке ^example\.com слеш перед точкой не случаен – эта строка является регулярным выражением, чтобы точка рассматривалась не как подстановочный символ, а как буквальная точка, используется слеш.

Всегда использовать WWW перед именем домена – универсальный вариант

Этот вариант подойдёт без изменений для любых сайтов: не нужно указывать имя хоста (доменное имя), а также не нужно указывать, используется ли протокол HTTP или HTTPS. Т.е. это более универсальный вариант.

RewriteEngine On
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

Первое условие проверяет, не является ли значение Host пустым (в случае HTTP/1.0). Второе проверяет, не начинается ли Host на www..

Обратите внимание на RewriteCond %{HTTPS}s ^on(s)|. Здесь используется довольно хитрый приём. Как было сказано чуть выше, переменная окружения %{HTTPS} содержит on, если сайт использует протокол HTTPS, и содержит off, если используется HTTP. К переменной окружения добавлена буквальная буква s, в результате происходит проверка строки %{HTTPS}s, которая, в зависимости от того, включен ли HTTPS или нет, может сводиться к ons или offs. Эта строка сравнивается с регулярным выражением ^on(s)|, где ^ — это символ начала строки. Символ трубы (|) говорит о том, что подойдёт любая альтернатива – стоящая перед этим символом или после. Перед этим символом стоит строка on(s), а после – ничего. Пустая строка соответствует любой сравниваемой строке. Исходя из этого, результат RewriteCond всегда будет сводиться к истине. Но в зависимости от того, какая часть регулярного выражения совпала: on(s) или пустая строка, обратная ссылка будет иметь значение «s» или будет пустой строкой. Обратная ссылка задаётся скобками, в которых находится буква s.

В результате http%1 при RewriteRule будет сводиться к https или к http.

Таким образом, это правило подойдёт для любого сайта, в нём не нужно прописывать свой домен как это нужно делать в предыдущем. Также не нужно заботиться о протоколе сайта.

Никогда не использовать WWW перед именем домена

Если вам не нужно, чтобы перед доменом в строке браузера были буквы www, то используйте следующее правило:

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

В нём замените http://example.com на имя вашего домена. Также обратите внимание на протокол. Во второй строке слеши используются для того, чтобы точки в регулярном выражении трактовались как буквальные символы (а не подстановочные).

Никогда не использовать WWW перед именем домена – универсальный вариант

Если вам нужно избавиться от www в адресной строке браузера, то следующее правило это сделает, переадресую запрос на аналогичный адрес, но без www:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^www\.
RewriteCond %{HTTPS}s ^on(s)|off
RewriteCond http%1://%{HTTP_HOST} ^(https?://)(www\.)?(.+)$
RewriteRule ^ %1%3%{REQUEST_URI} [R=301,L]

В этом наборе условий и правила не нужно указывать свой домен – конструкция является универсальной для любого сайта, также подходит для сайтов на HTTP и HTTPS.

Принудительное использование канонического имени с HTTPS и www

Если ваш сайт работает через протокол HTTPS и в качестве канонического имени вы выбрали использовать www перед именем домена, то вам поможет любое из следующих правил. У них нет принципиальной разницы, если какоео-то из них не подошло для ваших условий, просто попробуйте другое.

Первый способ:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

В этом примере имеются два правила перезаписи. Первое перенаправляет на HTTPS. Второе правило перезаписывает любой запрос с неверным доменом на использование www. Флаг [NC] означает совпадение независимо от регистра.

Второй способ:

RewriteEngine On
RewriteCond %{HTTP_HOST} (?!^www\.)^(.+)$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^ https://www.%1%{REQUEST_URI} [R=301,L]

Третий способ:

RewriteEngine on
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=302,L,NE]

Четвёртый способ (замените domain.ru на свой домен):

RewriteEngine On
RewriteCond %{HTTP_HOST} !^www\.domain\.ru [NC]
RewriteRule ^(.*)$ https://www.domain.ru/$1 [R=301,L]
RewriteCond %{SERVER_PORT} 80
RewriteRule ^(.*)$ https://www.domain.ru/$1 [R=301,L]

Канонический вид с HTTPS и без www

Если ваш сайт работает на HTTPS, но вы не хотите видеть www в адресной строке браузера перед именем домена, то используйте:

RewriteEngine on
RewriteCond %{HTTPS} !on
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
RewriteCond %{HTTP_HOST} ^www\.
RewriteCond %{HTTPS}s ^on(s)|off
RewriteCond http%1://%{HTTP_HOST} ^(https?://)(www\.)?(.+)$
RewriteRule ^ %1%3%{REQUEST_URI} [R=301,L]

Принудительное SSL и www для главного домена, принудительное SSL без www для всех поддоменов (кроме локальных)

RewriteEngine On
# для поддоменов: принудительно ssl и без www
RewriteCond %{HTTP_HOST} !\.local$ [NC]
RewriteCond %{HTTPS} !=on
RewriteCond %{HTTP_HOST} !^(www\.)?domain\.ru$ [NC]
RewriteCond %{HTTP_HOST} ^(?:www\.|)(.*)$ [NC]
RewriteRule ^.*$ https://%1%{REQUEST_URI} [R,L]

# для главных доменов: принудительно ssl без www
RewriteCond %{HTTP_HOST} !\.local$ [NC]
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{HTTP_HOST} ^domain\.ru$ [NC]
RewriteRule ^.*$ https://www.domain.ru%{REQUEST_URI} [R,L]

Замените domain.ru на имя вашего домена.

Принудительное добавление конечного слеша к адресу сайта

Если вам нужно добавить к URL конечный слеш (в том случае, если он отсутствует), то воспользуйтесь этим правилом перезаписи:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]

Удаление конечного слеша

Этот сниппет перенаправит пути, заканчивающиеся на слеши, на аналогичные, но без конечного слеша (кроме действительных директорий), к примеру http://www.example.com/blog/ на http://www.example.com/blog. Это важно для SEO, поскольку рекомендуется иметь канонический URL для каждой страницы.

Если вам нужно убрать из URL конечный слеш, то для этого используйте:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1[L,R=301]

Удаление конечных слешей из произвольных путей

Удаление конечных слешей из URL для веб-сайтов, размещённых в директории (как example.org/blog/):

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]

Удаление лишних слешей в адресе URL

Например, страница /catalog///stranica.html доступна и открывается. Чтобы избежать такой ситуации и не плодить бесконечное число дублей следует записать следующий редирект:

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} !=""
RewriteCond %{THE_REQUEST} ^[A-Z]+\s//+(.*)\sHTTP/[0-9.]+$ [OR]
RewriteCond %{THE_REQUEST} ^[A-Z]+\s(.*)//+\sHTTP/[0-9.]+$
RewriteRule .* http://%{HTTP_HOST}/%1 [R=301,L]

RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
RewriteRule . %1/%2 [R=301,L]

Здесь последовательно используется два правила для того, чтобы удалять многократные слеши из любой части URL: начала, середины, конца.

В первом правиле используется переменная %{THE_REQUEST}, она содержит полный запрос, примерно следующего вида:

GET /index.html HTTP/1.1

Для разделения частей запроса в выражениях условий, используется \s, которая означает белые пробелы.

Контроль доступа и блокировка хотлинка

Ограничение доступа по IP

Модуль mod_rewrite умеет переадресовывать, показывать различные страницы или блокировать доступ в зависимости от IP пользователя. Но если вам нужно просто заблокировать доступ для определённых IP, либо разрешить доступ определённым IP, но намного более удобным и лучшим вариантом будет использовать другой модуль, отвечающий за Контроль доступа к сайту (по ссылке подробная инструкция и множество примеров ограничения доступа к папка и отдельным файлам).

Запрет доступа к скрытым файлам и директориям

Скрытые файлы и директории (это те, чьи имена начинаются на точку .), должно в основном, если не всегда, быть защищены от просмотра веб-клиентами. Примеры таких файлов и папок: .htaccess, .htpasswd, .git, .hg

RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} -d [OR]
RewriteCond %{SCRIPT_FILENAME} -f
RewriteRule "(^|/)\." - [F]

В качестве альтернативы, чтобы запутать атакующего, при попытке открыть такие файлы можно вызвать ошибку «Not Found».

RedirectMatch 404 /\..*$

Запрет хотлинка изображений

Хотлинк (англ. hotlink) – включение в веб-страницу файлов-изображений или других ресурсов с чужого сервера.

При использовании следующих правил вам нужно отредактировать домен example.com на имя вашего сайта.

Также при тестировании помните о кэшировании (если оно включено, то изображении некоторое время всё равно будет отдаваться из кэша).

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?example.com [NC]
RewriteRule \.(jpe?g|png|gif|bmp)$ - [NC,F,L]

Приведённый выше вариант разрешит отправку изображений при пустом реферере («Blank Referrers»).

Что такое пустой реферер? Некоторые посетители имеют персональные файерволы или антивирусные программы, которые удаляют информацию о реферере (referrer) страницы, которую отправляет ваш веб-браузер. Защита от хотлинка основывается на этой информации. Поэтому если вы выберите запрет отправки изображений пользователям с пустым реферером, то вы заблокируете этих пользователей. Также это не позволит пользователям напрямую получать доступ к изображению, если они набрали его URL в браузере.

Допустим, вы не хотите разрешать «пустой реферер», тогда используйте следующий вариант:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?example.com [NC]
RewriteRule \.(jpe?g|png|gif|bmp)$ - [NC,F,L]

Допустим вы хотите показать изображение в духе «STOP HOTLINKING», тогда используйте следующий метод:

RewriteEngine on
# Удалите следующую строку, если вы хотите запретить доступ с пустым реферером
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?example.com [NC]
RewriteRule \.(jpe?g|png|gif|bmp)$ - [NC,F,L]

RewriteRule \.(jpe?g|png|gif|bmp) http://example.com/blocked.png [R,L]

Не забудьте поменять адрес изображения (http://example.com/blocked.png) на свой. Также убедитесь, что это изображение НЕ защищено от хотлинка, в противном случае ваш сервер попадёт в бесконечную петлю.

Запрет хотлинкинга только для определённых доменов

Иногда нужно отключить хотлинкинг изображений только для некоторых плохих парней. Для запрета хотлинка только от определённых доменов, таких как blockurl1.com, blockurl2.com и blockurl3.com, но разрешения любым другим сайтам вставлять ваши изображения:

RewriteEngine On
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?blockurl1\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?blockurl2\.com/ [NC,OR]
RewriteCond %{HTTP_REFERER} ^http://(.+\.)?blockurl3\.com/ [NC]
RewriteCond %{REQUEST_URI} !blocked\.gif$ [NC]
RewriteRule .*\.(jpe?g|gif|bmp|png)$ http://example.com/blocked.gif [L]

Вы можете добавить столько различных доменов, сколько вам нужно. Каждая строка RewriteCond должна заканчиваться флагами [NC,OR]. NC означает игнорировать регистр. OR означает логическое ИЛИ, т.е. правило сработает, если совпал этот домен или любой другой. Последний домен в списке идёт без флага OR, поскольку строки RewriteCond заканчиваются.

Последняя строка содержит URL "http://example.com/blocked.gif", который содержит изображение, которое будет показываться когда совпадут перечисленные условия – т.е. сработает запрет хотлинка.

Строка RewriteCond %{REQUEST_URI} !blocked\.gif$ [NC] ОТКЛЮЧАЕТ запрет хотлинка для изображения, которое показывается в случае срабатывания правил – это позволяет избежать бесконечного цикла.

Вы можете показывать сообщение об ошибке 403 Forbidden вместо изображения. Для этого замените последнюю строку в предыдущем примере на:

RewriteRule .*\.(jpe?g|gif|bmp|png)$ - [F]

Разрешение хотлинка для определённых сайтов

Чтобы разрешить хотлинк для определённых сайтов, укажите в следующих правилах свой сайт и сайты, которым вы хотите предоставить разрешение на вставку ваших картинок:

RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https?://(.+\.)?example.com [NC]
RewriteCond %{HTTP_REFERER} !^http://(www\.)?goodsite\.com/.*$ [NC]
RewriteRule .*\.(jpe?g|gif|bmp|png)$ - [F]

Блокировка пользователя по рефереру (Referrer)

Блокировка пользователей на основе ссылающегося домена. Это запрещает доступ для всех пользователей, кто пришёл (отправлен с) определённого домена:

RewriteEngine on
RewriteCond %{HTTP_REFERER} somedomain\.com [NC,OR]
RewriteCond %{HTTP_REFERER} anotherdomain\.com
RewriteRule .* - [F]

Замените somedomain.com и anotherdomain.com на действительные значения доменов (сайтов), которые вы не любите.

Блокировка плохих ботов, клонеров сайтов, офлайн браузеров

Для отключения доступа ботам и другим программам:

RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_USER_AGENT} ^Anarchie [OR]
RewriteCond %{HTTP_USER_AGENT} ^ASPSeek [OR]
RewriteCond %{HTTP_USER_AGENT} ^attach [OR]
RewriteCond %{HTTP_USER_AGENT} ^autoemailspider [OR]
RewriteCond %{HTTP_USER_AGENT} ^Xaldon\ WebSpider [OR]
RewriteCond %{HTTP_USER_AGENT} ^Xenu [OR]
RewriteCond %{HTTP_USER_AGENT} ^Zeus.*Webster [OR]
RewriteCond %{HTTP_USER_AGENT} ^Zeus
RewriteRule ^.* - [F,L]

Обратите внимание, что список неполный и (возможно), неактуальный. Дополняйте/редактируйте список на основе анализа логов ваших веб-сайтов.

Если вместо блокировки доступа, вы хотите отправлять их на какие-нибудь адские веб-сайты по вашему выбору, то замените последнюю строку на:

RewriteRule ^.*$ https://www.nsa.com [R,L]

Или отправьте их на виртуальную чёрную дыру фальшивых email адресов:

RewriteRule ^.*$ http://english-61925045732.spampoison.com [R,L]

Запрет доступа к файлу или директории в определённые периоды времени

Закрытие доступа в полночь:

RewriteCond %{TIME_HOUR} ^12$
RewriteRule ^.*$ - [F,L]

Закрытие доступа с 12 до 15 часов:

RewriteCond %{TIME_HOUR} ^(12|13|14|15)$
RewriteRule ^.*$ - [F,L]

Следующий набор директив запрещает доступ с 18 часов до 7 часов утра. При попытке посетить сайт в этот промежуток времени, будет выдан ответ 403 Forbidden (флаг [F]):

RewriteEngine On
RewriteCond "%{TIME_HOUR}" ">=18" [OR]
RewriteCond "%{TIME_HOUR}" "<07"
RewriteRule "^" "-" [F]

Продолжение: «Полное руководство по mod_rewrite (часть 6): Продвинутые техники применения mod_rewrite».

Рекомендуется Вам:

Добавить комментарий

Ваш e-mail не будет опубликован.