Как модуль может определить, когда выводится страница «Отказано в доступе»?

16

Как модуль может определить, когда Drupal выводит страницу «доступ запрещен»?
Я знаю, как это сделать с Drupal 6; Мне нужно знать, как это сделать с Drupal 7.

киамалуно
источник

Ответы:

13

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

Я полагаю, вы можете добавить новую страницу в свой hook_menu(), а затем установить эту страницу в качестве обратного вызова ошибки 403. Когда вы нажмете свой обратный вызов в пользовательском меню, вы знаете, что выводите страницу «Отказано в доступе»!

OPI
источник
Это не очень хорошее решение для меня, так как это меняет вывод, а не только обнаруживает 403.
Fabien Quatravaux
12

Я делаю это в Boost 7.x. Это не красиво, но это делает работу.

function boost_page_delivery_callback_alter(&$callback, $set = FALSE) {
  if ($callback == 'drupal_deliver_html_page') {
    $callback = 'boost_deliver_html_page';
  }
}

function boost_deliver_html_page($page_callback_result) {
  global $_boost;

  // Menu status constants are integers; page content is a string or array.
  if (is_int($page_callback_result)) {
    // @todo: Break these up into separate functions?
    switch ($page_callback_result) {

      // …

      case MENU_ACCESS_DENIED:
        // 403 page.
        $_boost['menu_item']['status'] = 403;
        break;

      // …

    }
    // …
  }
  // …   
}
mikeytown2
источник
Это большой взлом, но он работает: то, что вы делаете, называется хищением. Вы подключаете свой собственный код на более раннем этапе, а затем воспроизводите основной код с минимальными изменениями.
Фабьен Кватраво
10

В Drupal 7 функция, которая возвращает уже установленные заголовки HTTP, это drupal_get_http_header () , для которой в качестве параметра требуется имя заголовка HTTP. Глядя на код authorize_access_denied_page () и drupal_fast_404 (), становится ясно, какие значения передать этой функции.

  // authorize_access_denied_page()
  drupal_add_http_header('Status', '403 Forbidden');
  watchdog('access denied', 'authorize.php', NULL, WATCHDOG_WARNING);
  drupal_set_title('Access denied');
  return t('You are not allowed to access this page.');
// drupal_fast_404()
if ($fast_paths && preg_match($fast_paths, $_GET['q'])) {
  drupal_add_http_header('Status', '404 Not Found');
  $fast_404_html = variable_get('404_fast_html', '<html xmlns="http://www.w3.org/1999/xhtml"><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL "@path" was not found on this server.</p></body></html>');
  // Replace @path in the variable with the page path.
  print strtr($fast_404_html, array('@path' => check_plain(request_uri())));
  exit;
}

Когда заголовок «Status» начинается с 403 , Drupal выводит страницу с отказом в доступе.

Убедитесь, что звонок drupal_get_http_header('Status')происходит поздно. Вызов во время hook_init()слишком рано, но вызов во время hook_page_alter()(или любой обработчик препроцессора темы) будет иметь обновленную информацию заголовка.

киамалуно
источник
Этот действительно хороший ответ. Однако следует отметить лишь один момент: он работает только в том случае, если страница не кэширована. Если страница уже была доступна ранее, drupal_get_http_header('Status')возвращается NULL.
Фабьен Кватраво,
4

Ваш модуль может перехватить значение " Default 403 (access denied) page", которое изменяется страницей " Administer > Site configuration > Error reporting":

  1. В hook_enable, используя variable_get/ variable_set, скопировать существующее значение для вторичных переменных и заменить переменный по собственному пути (который вы зарегистрировались с помощью hook_menu).

  2. измените форму «Отчет об ошибках», используя hook_form_FORM_ID_alterдля чтения / записи вторичной переменной

  3. Если вы хотите быть полностью невидимым для пользователя, вы можете позвонить на вашу страницу drupal_goto( the_value_of_the_secondary_variable ).

  4. В hook_disable, восстановите значение из вторичной переменной.


И все, ваш модуль получает уведомление чистым способом (и невидимым для пользователя), когда срабатывает «Отказано в доступе».

wildpeaks
источник
2

Конечно, вы могли бы использовать get_headers()функцию PHP ?

http://php.net/manual/en/function.get-headers.php

Первым элементом в возвращенном массиве будет код ответа. Если он содержит «403», то Drupal вернул страницу «Отказано в доступе».

Я не уверен, где будет лучшее место, чтобы позвонить. Возможно hook_exit(), в зависимости от ваших потребностей:

http://api.drupal.org/api/drupal/developer--hooks--core.php/function/hook_exit/6

Greg
источник
2

Это самый простой способ обнаружить отказ в доступе (403) и страницу не найдена (404) в Drupal 7.

// get the menu router item for the current page
$router_item = menu_get_item();

// if there is no router item, this page is not found
$is_page_not_found_404 = empty($router_item);

// if 'access' is empty for the router item, access is denied
$is_access_denied_403 = empty($router_item['access']);
Линдсей
источник
-2

Вы можете использовать модуль Панели для этого.

Модуль «Панели» позволяет администратору сайта создавать индивидуальные макеты для многократного использования. По своей сути это менеджер содержимого, который позволяет визуально создавать макет и размещать контент в этом макете. Интеграция с другими системами позволяет вам создавать узлы, которые используют это, целевые страницы, которые используют это, и даже переопределять системные страницы, такие как таксономия и страница узла, чтобы вы могли настроить макет вашего сайта с очень тонкими разрешениями.

Умутан Уян
источник