Еще 500 рэ пришли. Кто отправил с Яндекс.Деньги, маякните логин. Я же все записываю :-)
Здравствуйте, уважаемые знатоки MODx Evo! Ответьте пожалуйста на несколько вопросов, касательно разработки модуля для MODx Evo (1.0.10).
И комменты мгновенно добавляются.
А вот этот баг — один из самых сложных и злостных, с которым я сталкивался в MODX-е… На официальном форуме вопрос задали уже более двух месяцев назад (хотя я столкнулся гораздо раньше), и до сих пор нет четкого ответа на него. Но вот вчера у меня опять вылезла эта бяка на сайте, и я тогда сел основательно ее копать. Суть проблемы заключается в том, что как бы админка вся работает и все клева, но при сохранении документа получаем сообщение Access denied (или Доступ запрещен, в зависимости от языка админки). При чем самое интересное в том, что при сохранении документа через быстрое редактирование документ сохраняется, все ОК, а при редактировании в полном редакторе у нас ошибка доступа. Собственно, за 3 часа я получил боле менее вменяемый ответ на природу этого феномена, но самого решения у меня сейчас нет. Тем не менее под катом вас ждет перевод этого ответа и описание самых интересных моментов. Итак, когда я начал ковырять все это дело, я обратил внимание на то, что на сервер передается HTTP_MODAUTH='0', то есть ключ нулевой (именно нулевой, а не отсутствующий). То есть это и не полный ключ сессии, но и не отсутствие его. То есть с натяжкой можно считать, что ключ сессии есть. НО: при запросе на update документа из быстрого редактора документ нормально сохраняется, а при запросе на update из полного редактора у нас Access denied. При этом в обоих запросах присутствует HTTP_MODAUTH='0' (здесь и далее мы будем рассматривать только эти два запроса (быстрый и полные редактор), так как их принцип примерно общий, а результат разный). Так в чем же тогда фокус? На этот вопрос я получил ответ, когда более внимательно изучил modConnectorResponse. Вот самый интересный кусочек кода: if (!$isLogin && !isset($_SERVER['HTTP_MODAUTH']) && (!isset($_REQUEST['HTTP_MODAUTH']) || empty($_REQUEST['HTTP_MODAUTH']))) { $this->responseCode = 401; $this->body = $modx->error->failure($modx->lexicon('access_denied'),array('code' => 401)); } И вот самое интересное мне не сразу в глаза кинулось, а именно переменные $_SERVER['HTTP_MODAUTH'] и $_REQUEST['HTTP_MODAUTH']. То есть ключи одинаковые HTTP_MODAUTH, а массивы разные $_SERVER и $_REQUEST. Думаю, многие понимают что это за массивы и в чем их отличие, поэтому не буду их объяснять. Но вот что интересней всего: $_SERVER['HTTP_MODAUTH'] нигде не объявляется. То есть во всем ядре MODX-а нет где-либо присвоения значения этой переменной. Но ведь она не может просто так появиться… Тогда я полез ковырять JS-файлы, и вот такой интересный кусочек нашел в core/modx.layout.js: Ext.Ajax.defaultHeaders = { 'modAuth': config.auth }; Ext.Ajax.extraParams = { 'HTTP_MODAUTH': config.auth }; Ext.Ajax.extraParams — это параметры, передаваемые в запросе (по умолчанию для всех запросов). А вот Ext.Ajax.defaultHeaders — это заголовки запроса. И вот как раз их-то если специально искать не будешь, не увидишь. А они есть. ? А увидеть этот параметр мы можем в коде страницы админки. К примеру: <script type="text/javascript">Ext.onReady(function() { ...... MODx.load({xtype: "modx-layout",accordionPanels: MODx.accordionPanels || [], auth: "modx51b7a546bbe9a4.05164626_25223640a1da1e4.42369214"}); });</script> Формируется он в modManagerController. $siteId = $this->modx->user->getUserToken('mgr'); ........ MODx.load({xtype: "modx-layout",accordionPanels: MODx.accordionPanels || [],auth: "'.$siteId.'"}); modUser::getUserToken(): public function getUserToken($ctx = '') { if (empty($ctx)) $ctx = $this->xpdo->context->get('key'); return isset($_SESSION['modx.'.$ctx.'.user.token']) ? $_SESSION['modx.'.$ctx.'.user.token'] : ''; } Вот он методом modUser::getUserToken() и получает токен контекста, который и участвует во всей этой цепочке. И что самое интересное, токен может быть и нулевым, лишь бы он был хоть каким-то, и везде имел одинаковое значение (и в $_SERVER['HTTP_MODAUTH'], и в $_REQUEST['HTTP_MODAUTH']). Тогда будет считаться, что пользователь корректно авторизован. И в большинстве случаев так и происходит. НО, в случае отправки запроса из полного редактора страницы этого не происходит. Просто потому что его механизм отправки данных отличается, и он не отправляет modAuth-заголовок на сервер. В результате чего переменная $_SERVER['HTTP_MODAUTH'] пустая, и мы имеем Action denied. Каждый может проверить этот баг очень просто (на MODX Revolution 2.2.8 и выше). Просто выполните в Console (или другим способом) этот простой php-код: $_SESSION['modx.mgr.user.token'] = '0'; То есть просто обнулите сессию в контексте mgr, после чего обновите страницу админки. Админка работать будет, но попробуйте обновить документ в полном редакторе, и скорее всего получите Access denied. Резюме: в какой-то момент токен сессии обнуляется (по какой причине — я не знаю. У меня есть подозрение, что такое случается, когда ставишь галочку Запомнить, но в админку потом не заходишь несколько дней). Потом через несколько дней заходишь, и как бы авторизован, но вот с таким обнуленным токеном. И в итоге получается, что как бы авторизован, но не полноценно. И при этом ты и не не авторизован, то есть нет требования авторизоваться.
да никаких сарказмов! то что переносишь я еще седня ночью видел) просто реально стал нормально сайт открываться, без тормозов.
Если это был сарказм :-) (по поводу неработы сайта), то я вот здесь по этому поводу отписался. А если без шуток, то работа сайта действительно улучшилась по одной простой причине: на modxcloud.com нет memcache, а ливстрит на файловом кеше — хуже, чем вообще без кеша. А вот сейчас я поставил memcache и перевел ливстрит на него, и это дает большой плюс по скорости его работы.
Сегодня modxclub.ru выдавал стандартную страницу апача «It`s work!». А получилось это вот по какой причине: я перевез сайт на digitalocean.com, настроил апач и нгинкс, и все нормально работало. Но последний штрих во всем этом был — установка основного доменного имени modxclub.ru для всего сервера через панель хостинга и в hostname. А как оказалось, дефолтная настройка хоста в апаче, которая идет без указания ServerName (файл etc/apache2/sites-available/default) использует по умолчанию указанный hostname, даже если он прописан где-нибудь в отдельном конфиге. В общем, после перезагрузки апач для modxclub.ru стал отдавать дефолтный хост. А так как я днем спал, я несколько часов находился в неведении, что сайт не работает. Вот такой казус… P.S. в дефолтную настройку пока добавил ServerName default. Потом буду разбираться как он при этом работает, но главное сейчас — modxclub.ru работает.
Кстати, modxclub.ru таки переехал на digitalocean.com