Использование mod_rewrite для перенаправления на основе параметра строки запроса

#apache #.htaccess #redirect #mod-rewrite #url-rewriting

Вопрос:

Я пытаюсь заставить что-то работать с mod_rewrite, но не совсем уверен, что это вообще возможно.

Скажем, у меня есть какая-то просьба, например:

 https://www.example.com?h=somerandomvalueamp;u=www.another.example/content  

Я хотел бы взять значение u параметра и переписать запрос, используя это значение, поэтому из приведенного выше примера запроса я хотел бы переписать его следующим образом

 https://www.another.example/content  

Итак, в основном, запрос:

 https://www.example.com?h=somerandomvalueamp;u=www.another.example/content  

Перенаправляет на:

 www.another.example/content  

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

Любая помощь или руководство здесь очень ценятся!

Ответ №1:

Я видел другие примеры, когда люди фиксируют и используют параметры как часть переписанного пути

Да, это возможно. Основной принцип тот же:

 RewriteEngine On  RewriteCond %{QUERY_STRING} (?:^|amp;)u=([w./-]{6,})(?:amp;|$) RewriteRule ^$ https://%1 [QSD,R=302,L]  

%1 является обратной ссылкой на группу захвата в предыдущем шаблоне. т. Е. Значением параметра u URL.

([w./-]{6,}) это всего лишь очень элементарная проверка на соответствие полувидимому URL-адресу. Это можно улучшить.

(?:^|amp;) Префикс в регулярном выражении гарантирует, что мы соответствуем только параметру u URL, а не любому параметру URL, который просто заканчивается u .

Это перенаправляет запросы только на корневой каталог, как в вашем примере. Злоумышленник может превратить ваш сайт в ретранслятор для переадресации трафика.

Однако без дополнительной проверки перенаправляемого URL-адреса это потенциально может привести к злоупотреблениям и не должно использоваться.

ОБНОВЛЕНИЕ № 1:

Например, вы можете ограничить имена хостов, на которые можно перенаправлять, рядом RewriteCond директив:

 RewriteCond %{QUERY_STRING} (?:^|amp;)u=([w./-]{6,})(?:amp;|$) RewriteCond %1 ^(www.another.example/.*) [OR] RewriteCond %1 ^(www.two.example/.*) [OR] RewriteCond %1 ^(www.three.example/.*) [OR] RewriteCond %1 ^(www.four.example/specific/path/to/file.html) RewriteRule ^$ https://%1 [QSD,R=302,L]  

%1 Обратная ссылка (которая содержит захваченную группу из последнего совпадающего шаблона) соответствует полному URL-адресу, отправленному в параметре u URL. Это зависит от того факта, что RewriteCond директивы заканчиваются «рано», когда условие выполнено.

Если у вас много определенных URL-адресов, вы можете создать RewriteMap их в конфигурации сервера и выполнить поиск, чтобы проверить допустимые URL-адреса.

В качестве альтернативы, перепишите запрос в сценарий на стороне сервера (например. PHP) и вместо этого управлять проверками и перенаправлением в скрипте.


ОБНОВЛЕНИЕ № 2:

Работает ли этот пример также, если параметр u является закодированным URL-адресом?

В настоящее время нет. Переменная QUERY_STRING сервера не декодирована в%. Чтобы разрешить значение параметра с кодировкой URL (%-кодировка), вам нужно будет включить % в класс символов регулярного выражения, соответствующий URL — адресу, и включить флаг NE ( noescape ) в RewriteRule директиву, чтобы предотвратить двойное кодирование символов с кодировкой %в ответе на перенаправление.

Например:

 RewriteCond %{QUERY_STRING} (?:^|amp;)u=([w%./-]{6,})(?:amp;|$) : RewriteRule ^$ https://%1 [NE,QSD,R=302,L]  

Комментарии:

1. Спасибо за помощь. Вы правы в том, что это опасно на практике — проще говоря, предполагается, что это перенаправит 1000 различных URL-адресов, все из которых я не смог бы учесть за какую-то секунду перезаписи. Я собираюсь отметить ваш ответ как правильный, так как он обычно работает так, как описано, однако знайте, что я решил рассмотреть другие варианты, чтобы мы с вами могли спать немного крепче.

2. Работает ли этот пример также, если параметр u является закодированным URL-адресом?

3. @JasonWordtmann В настоящее время нет. Я обновил свой ответ примером, в котором будет разрешен параметр URL с кодировкой%.