Должен ли я избежать косой черты /
в RewriteCond
?
Под «экранировать косую черту» вы действительно имеете в виду «должен ли я соответствовать косой черте, закодированной в URL, или нет?». Это полностью зависит от HTTP-запроса к вашему серверу.
Но я проверяю https://serverfault.com/a/968916/280923 и он сказал: «Слэш (/
) не нужно экранировать». Так что я в замешательстве.
Связанный вопрос/ответ не имеет отношения к текущей проблеме. Этот вопрос касается экранирования обратной косой черты в директивах / регулярных выражениях Apache, а не URL-адресов с кодировкой URL (или с кодировкой %), с которыми вы имеете дело здесь. Это два очень разных типа методов «убегания» для разных целей.
То, с чем вы имеете дело, - это URL-адреса с кодировкой %. Как URL отображается в HTTP-запросе. Различные части URL-адреса (особенно «путь» и «строка запроса») имеют разные требования к кодированию. Будь то конкретный персонаж потребности быть закодированным с помощью % зависит от того, будет ли он иначе иметь особое значение в этом контексте.
Как определено в RFC3986, косая черта (/
) строго не обязательно кодировать % в части строки запроса URL-адреса. Однако функции кодирования URL-адресов (например, в PHP и JavaScript) часто кодируют этот символ с помощью %-кодирования. (Я думаю, что это в значительной степени исторически, поскольку некоторые старые реализации, как сообщается, неправильно обрабатывали незакодированную косую черту - ссылка RFC3986.)
Однако независимо от того, является ли персонаж потребности чтобы быть закодированным в URL (чтобы свести на нет его особое значение), любой символ может быть закодирован в %, и это должно рассматриваться так же, как буквальный (незакодированный) символ.
Нужно ли вам соответствовать /
(расшифровано) или %2F
(закодировано) зависит от того, закодирован ли этот символ в запросе с помощью %-кодирования.
Ваша проблема в том, что СТРОКА ЗАПРОСА
серверная переменная не декодируется %, в отличие от URL-пути, которому соответствует Правило перезаписи
шаблон.
Но... нужно ли проверять как %-decoded /
и %-закодировано %2F
? Предположительно, вы постоянно ссылаетесь только на тот или иной (канонический) URL. Таким образом, любые запросы к неканоническому URL-адресу должны быть введены вручную или ошибочно связаны третьей стороной. Вы получаете запросы к обоим? Каковы последствия отказа от перенаправления неканонического URL-адреса?
В противном случае, да, вам нужно будет проверить оба (и, возможно, все варианты/случаи). Хотя это, скорее всего, будет только /база знаний/
или же %2Fбаза знаний%2F
. Но обратите внимание, что это может быть %2F
(верхний регистр) или %2f
(нижний регистр). Верхний регистр - это просто соглашение. Необходимость проверки смешанной кодировки, такой как %2Fбаза знаний/
должно быть очень редко. Но доведенное до крайности, это то же самое, что и %2f%6b%6e%6f%77%6c%65%64%67%65%62%61%73%65%2f
. Необходимость обработки всех этих вариантов зависит от вероятности получения такого запроса и серьезности несоответствия правил.
Итак, чтобы соответствовать обоим /база знаний/
и %2Fбаза знаний%2F
(без учета регистра) вы можете использовать что-то вроде:
RewriteCond %{QUERY_STRING} ^rp=(/|%2[Ff])база знаний(/|%2[Ff])
Вы можете избежать класса символов [Фф]
и использовать Северная Каролина
флаг, чтобы сделать все сравнение нечувствительным к регистру. Например:
RewriteCond %{QUERY_STRING} ^rp=(/|%2F)база знаний(/|%2F) [NC]
В Apache 2.4 вы можете использовать отменить экранирование ()
функция в выражении Apache с RewriteCond
директива для декодирования URL СТРОКА ЗАПРОСА
прежде чем делать сравнение. Однако на самом деле это не поможет вам, поскольку не декодирует косые черты, т.е. %2F
или же %2f
остается в соответствии с запросом (но любые другие символы %-декодируются). Например:
RewriteCond expr "unescape(%{QUERY_STRING}) =~ m#^rp=(/|%2[Ff])knowledgebase(/|%2[Ff])#"
Это позволит вам соответствовать рп=%2f%6b%6e%6f%77%6c%65%64%67%65%62%61%73%65%2f
.
Или, если вы не ожидаете никаких закодированных символов URL в строке запроса, вы можете просто заблокировать любой запрос, который их отправляет! Например, следующее должно быть в верхней части вашей конфигурации:
# Блокировать любой запрос, содержащий символ в кодировке % в строке запроса
RewriteCond %{QUERY_STRING} %[\da-f]{2} [NC]
Правило перезаписи ^ - [R=400]