Авторские статьи Mod_Rewrite. Что, как, с чем?

Discussion in 'Статьи' started by darky, 18 Nov 2006.

  1. darky

    darky ♠ ♦ ♣ ♥

    Joined:
    18 May 2006
    Messages:
    1,773
    Likes Received:
    825
    Reputations:
    1,418
    mod_rewrite ... что это? как говорит вики -
    т.е. некий модуль для вэб сервера, позволяющий модифицировать линки.. Вообще сам энжин рерайта существует как на для апача, так и для мелкомягкого IIS, и даже для java платформ =) В этой статье пойдет речь именно о mod_rewrit'е для апача.

    Все что от нас понадобится - файл .htaccess в корне, если же у вас он есть.. то нужно просто напросто дописать в нем определенные строки.. ну и конечно если хостер до сих пор не установил этот модуль, то его нужно немного попинать ногой..)
    Лично я юзаю полные ссылки в .htaccess, если же вы хотите использовать относительные ссылки типа /index.php?blabla=31337 то желаьельно включить в файлик следущие строчки, которые хоть и немного но ускоряют работу
    то бишь если у вас сайт в www, а опция не врублена, то апач будет пытаться найти файл Index.php сначала в /home/ потом в /home/htdocs/, ну и в конце концов наткнется на /home/htdocs/www/index.php. Мелочь конечно, но пару сотых секунды сэкономите..) либо можно в каждом файле писать перед рерайтрул он сл. фразу
    PHP:
    Options +FollowSymLinks
    Вообще у него можно найти довольно таки много вариантов применения.. самый популярный из них - это преобразование ссылки в более читабельный вид ) .. ну найдите мне человека которому бы понравилась ссылка вида
    Сделаем из нее например
    Для этого нам нужно сначала подключить сам RewriteEngine
    PHP:
    RewriteEngine On
    затем переписывается сам url
    PHP:
    RewriteRule ^ ([a-z]+)/([a-z0-9]+).htmindex.php?action=$1;forum=$2
    Разберемся с этой несложной конструкцией...

    RewriteRule просто задает начало строки переписывания.

    ([a-z]+)показывает что все до слэша заменяется маленькими латинскими буквами от a до z (все записывается в переменную $1)

    дальше после слэша видим ([a-z0-9]+).htm, т.е. здесь мы заменяем все что после слэша мелкой латиницей от a до z и цифрами от 0 до 9 (переменная $2), а после этого добавляем в конец url'а расширение htm. Как вы понимаете таких .htm файлов у вас на сайте не было и не будет, просто так ссылки показываются в более удобном виде.

    Тут главное запомнить - после RewriteRule идет 1ое - как переделывать, а затем что переделывать, думаю не особо сложно =)

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

    Расмотрим еще один небольшой пример (тут я использую уже относительные ссылки)
    сделаем из
    Перепишем под
    Сначала как я сказал выше подрубим
    PHP:
    Options +FollowSymLinks
    потом
    PHP:
    RewriteEngine On 
    RewriteRule 
    ^([^/]+)/([0-9])-(.+)\.htmindex.php?forum=$1&nickname=$2&userID=$3
    первая строчка понятна, раберем 2ую. ([^/]+) - до слэша разрешаем юзать любые символы (ну а вдруг у нас в названии форума попадется и цифра.. хотя можно и что-то вроде ([a-zA-Z0-9]+), но тут не будет показываться например тире).
    После ([0-9])-(.+) т.е. во 2ой части "конечного файла" мы вписываем саму переменную $2 (которая равна "hacker"), а в первую записываем только цифры (у нас это например айди юзера равное 31337) ( ([0-9]) ).
    Ну и добавляем в конце расширение. Вторая часть строки в комментрариях не нуждается.. т.е. там всего лишь указано что переписывать. Все 3 значения переменных.

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

    что мы можем им сделать... рассмотрим на примере
    PHP:
    RewriteRule ^(forum)/(topicID)$ /read-$1-topic-$2
    Причем образуется
    PHP:
    read-#forum-and-#topicID
    где #forum название форума, #topicID айдишник топика.

    Всем переменным дан номер по мере их появления, и условие и правило имеют по 2 переменные (в данном примере естесно, а вообще хоть 100, кто вам мешает), которые задаются круглыми скобками, потому чтобы юзать их, вам надо поставить их в туда, где они вам нужны в конечном результате-ссылке.


    Скомбинируем и правило и условие
    Этим мы перепишем ссылку с многочисленными параметрами до сл типа
    PHP:
    forumname-forum-topicID
    Можно в принципе и без слешей. но имхо надписи будут сливаться =)

    Тут на ум приходила веселая регулярка
    PHP:
    RewriteRule ^([^.]+)$ /index.php
    После прочтения вам не кажется немного странной ? =) Правы.. она переписывает все по правилу все, кроме любого символа, сам лично не пробовал, но кто проверит что выдаст апач на это просьба отпишитесь =)

    Итак. Мы научились юзать RewriteRule и RewriteCond, юзать мод рерайт для обеспечение безопастности на сервере (например от sql inj) и просто для украшения и запоминания ссылок.

    Спасибо за прочтение :) 2nd part coming up
    (ц) blackybr
     
    #1 darky, 18 Nov 2006
    Last edited by a moderator: 2 Jan 2007
    15 people like this.
  2. 1ten0.0net1

    1ten0.0net1 Time out

    Joined:
    28 Nov 2005
    Messages:
    473
    Likes Received:
    330
    Reputations:
    389
    Вопсчем, трудился молодец - но цвета поменяй!!!! Я, например, когда пишу, стараюсь красным выделять ошибки - зеленым важную информацию, голубым ссылки, а все техническое - оранжевым. А у тебя - щас посчитаю - как минимум 9 разных цветов, немного читабельность теряется. А, вообще, статья хорошая - сам мод описал, еще и по минимуму с регуляркой познакомил тех, кто не знал.

    P. S.
    - а вот это ты зря... Имхо, надо было предупредить читателей о существовании одного из самых популярных эксплоитов для этого мода, для большинства веток Апача.
    _http://milw0rm.com/exploits/2237
     
    1 person likes this.
  3. darky

    darky ♠ ♦ ♣ ♥

    Joined:
    18 May 2006
    Messages:
    1,773
    Likes Received:
    825
    Reputations:
    1,418
    имхо если он еще не стоит, то вряд ли хостер поставит старую версию..) + чтобы заставить заработать сплоит надо пересчитать адреса..это раз.. а второе кое что заменить.. и вообще..))) статья не про это ))
     
    #3 darky, 18 Nov 2006
    Last edited: 18 Nov 2006
  4. darky

    darky ♠ ♦ ♣ ♥

    Joined:
    18 May 2006
    Messages:
    1,773
    Likes Received:
    825
    Reputations:
    1,418
    Part 2. Небольшое дополнение.

    Пару слов о том, как можно использовать mod rewrite для повышения секурности сайта, ограничения контента, прав доступа и тд и тп (без использования языков web программирования)

    Что же еще может mod rewrite? а может он довольно-таки много. Как я уже писал, RewriteCond определяет правила условия, и всегда предшествует RewriteRule. Т.е. RewriteRule в таком случае работает только при верном условии. Rewrite module воспринимает также и сервреные переменные, что не может не радовать ) Вот некоторые из них, которыми приходится довольствоваться довольно-таки часто:

    HTTP_USER_AGENT - юзер агент (например Opera/9.10 (Windows NT 5.1; U; ru))
    HTTP_REFERER - Реффер (т.е. сайт с которой вы пришли на конечный сайт)
    HTTP_COOKIE - передаваемые кукисы =)
    HTTP_FORWARDED - адрес пользователя который сейчас на страничке
    HTTP_HOST - адрес сайта (без http://)
    HTTP_PROXY_CONNECTION - становленно в том случае, если клиент пришел через 'прозрачный' прокси-сервер.
    HTTP_ACCEPT - уточнее типа информации (так называемых медиа-типов) принимаемой браузером на данной страничке, например text/plain, text/html, image/gif, image/jpeg)
    REMOTE_ADDR - ваш ip
    REQUEST_METHOD - метод используемый для выдачи запроса (GET, PUT, POST и тд)
    SCRIPT_FILENAME - полный путь к выполняемому скрипту на сервере
    PATH_INFO - все что следует за именем скрипта при его вызове
    QUERY_STRING - строка запроса


    Предположим у нас есть сайт http://site.com
    Мы почему-то ужастно не хотим, чтобы кто-то напрямую имел акцесс к какому либо типу файлов, например картинкам jpg, png (ну т.е. только скрипты могли это делать). Можно попробовать сделать это с помощью mod_access, чем-то типа с .htaccess в корне с содержанием:
    PHP:
    <FilesMatch "\.(jpg|png)$"
      
    Order Deny,Allow 
      Deny from all 
    </FilesMatch>
    Но недостаок в том, что он будет запрещать доступ и вам и скриптам, вызывающие/открывающие картинки. Делаем это с помощью mod_rewrite
    PHP:
    Options +FollowSymLinks 
    RewriteEngine On 
    RewriteCond 
    %{HTTP_REFERER} . 
    RewriteCond %{HTTP_REFERER} !^http://(www\.)?site\.com(/.*)?$ 
    RewriteRule \.(jpg|png)$
    Первые две строчки понятны. Дальше видим условие - при HTTP_REFERER содержащим site.com (регулярки см. выше) то тогда разрешается просмотр картинки.
    Когда это может помоч? Ну например у на есть фотоархив и есть счетчик и мы хотим знать точное кол-во посетителей. Но ведь когда фотка индексируется в поисковике, и человек проходит по ссылке из того же яндекса - в реферере указан сам яндекс и не факт, что ссылка будет не на прямую картинку. Так называемый hot-linking Думаю понятно :)


    Теперь сделаем подобие авторизации.. правда использую опять же Mod_rewrite ..
    Т.к. я уже сказал что мы не будем использовать php,perl и тд, то прийдется обойтись и без бд =)

    Для этого разберем еще одну директиву мода - RewriteMap, которая используется в правилах замены разными mapping ф-ями к областям переписки с помощью rewriterule через rewritecond..

    Авторизацию будем проводить по файлу сессиям в auth.txt который находится вне WWW. Пусть полный путь на сервере к сайту /home/user/www/
    Создадим файл /home/user/auth.txt с таким содержимым:
    PHP:
    # session  1 
    abcdefghijkl  1
    Дальше разберемся что же будет у нас в .htaccess
    PHP:
    Options +FollowSymLinks 
    RewriteEngine On
    RewriteMap sessionids txt
    :/home/user/auth.txt

    # сессии нет вообще
    RewriteCond %{QUERY_STRING} !^(.*&)?sessionid= [NC,OR] 
    RewriteCond %{QUERY_STRING} ^(.*&)?sessionid=(&.*)?$ [NC
    RewriteRule .* - [F,L

    # сессиии нет в файле
    RewriteCond %{QUERY_STRING} ^(.*&)?sessionid=([^&]+)(&.*)?$ [NC
    RewriteCond ${sessionids:%2|0} ^0
    RewriteRule .* - [F,L]
    или для файла вида (заюзаем более секурную версию - сессия + айпи)
    PHP:
    # session-ip  1 
    blablbalbalb-127.0.0.1  1
    получим немного по-другому
    PHP:
    RewriteCond %{QUERY_STRING} ^(.*&)?sessionid=([^&]+)(&.*)?$ [NC]   
    RewriteCond %2-%{REMOTE_ADDR} ^(.+)$   RewriteCond ${sessionids:%1|0} ^0$   
    RewriteRule .* - [F,L]
    Все что тут сделано, я уж описывал. Еще раз повторю -

    берем QUERY_STRING (Т.е. строку запроса), и проверяем ее на наличие сессии черех txt файл (с тем же результаом можно сделать через .php файл, который обращается к бд).

    RewriteCond%2-%{REMOTE_ADDR} ^(.+)$ - %2 взято из первого RewriteCond, наша сессия
    потом переменная сессии и айпи (он у нас тоже есть в .txt файле) заносим в одну переменную - %1


    RewriteCond ${sessionids:%1|0} ^0$


    ${sessionids:%1|0} - проверка по RewriteMap
    sessionid - имя самой Rewrite Map

    %1 - переменная, о которой сказал выше (сессия + айпи.)

    0 - просто дэфолтная переменная


    Смысл в том, что если проверка по файлу возвращает положиетльный резуультат и строчка с данными существует для данной Rewite Map, то возвращается 1 (та самая единичка уоторую я ставлю в конце каждой строчки в файле) auth.txt, в противном случае возвращается 0 ( ^0$ обозначает что-то типа "присвоим ему 0" ). Если проверка вообще не осуществилась, то возвращается опять же 0, после чего мод рерайт продолжает свою работу, предвариетльно послав Forbidden ( [F] ).

    (ц) blackybr



    См. также
    http://httpd.apache.org/docs/1.3/mod/mod_rewrite.html
    http://en.wikipedia.org/wiki/Rewrite_engine
     
    #4 darky, 20 Jan 2007
    Last edited: 20 Jan 2007
  5. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    все ок, одно добавление - если он не установлен, некий его функционал можно заменить с помощью ErrorDocument 404.php, а в 404.php парсить параметры и выдавать нужные страницы.
     
  6. nerezus

    nerezus Banned

    Joined:
    12 Aug 2004
    Messages:
    3,191
    Likes Received:
    729
    Reputations:
    266
    _Great_, мы тогда теряем POST-данные.
     
  7. _Great_

    _Great_ Elder - Старейшина

    Joined:
    27 Dec 2005
    Messages:
    2,032
    Likes Received:
    1,119
    Reputations:
    1,139
    согласен, но я же сказал - некоторый функционал, не весь.
     
  8. FurA

    FurA Member

    Joined:
    1 Aug 2005
    Messages:
    18
    Likes Received:
    5
    Reputations:
    0
    Почитал, порадовало.
    От себя добавлю, что неправильная тюнинговка реврайта может пойти на руку ддосерам (самый банальный пример - не прописать докьюмет рут. если у вас шаред - то пиши пропало =) ).
     
  9. Student :)

    Student :) Elder - Старейшина

    Joined:
    9 Feb 2007
    Messages:
    278
    Likes Received:
    18
    Reputations:
    -15
  10. igorf()x

    igorf()x Elder - Старейшина

    Joined:
    17 Oct 2007
    Messages:
    138
    Likes Received:
    53
    Reputations:
    5
    http://www.egoroff.spb.ru/portfolio/apache/mod_rewrite.html
     
  11. satana8920

    satana8920 Палач Античата

    Joined:
    22 Sep 2006
    Messages:
    396
    Likes Received:
    138
    Reputations:
    6
    Опишите пожалуйста как его потом обойти что б спам бота написат =)))
    статья класс