Проверьте, есть ли у пользователя доступ к определенной странице

23

Как я могу определить, есть ли у пользователя разрешение на доступ к определенной странице?

Фарзан
источник
Вы не указали, какую версию Drupal вы используете. Более подробная информация о вашей цели также будет полезна; в наиболее распространенных случаях Drupal автоматически обрабатывает доступ к меню.
Дилан Тэк

Ответы:

25

Если вы хотите проверить, есть ли у вошедшего в систему пользователя доступ к странице, вы можете использовать следующий код:

if ($router_item = menu_get_item($path)) {
  if ($router_item['access']) {
    // The user has access to the page in $path.
  }
}

$path это путь к странице, которую вы хотите проверить (например, узел / 1, администратор / пользователь / пользователь).

Код работает в Drupal 6 и более поздних версиях, и он используется из menu_execute_active_handler () .

Причина, по которой я не предлагаю напрямую вызывать обратный вызов доступа, заключается в том, что аргументы, которые необходимо передать этой функции.

Код, используемый _menu_check_access (), следующий (Drupal 7):

$arguments = menu_unserialize($item['access_arguments'], $map);
// As call_user_func_array is quite slow and user_access is a very common
// callback, it is worth making a special case for it.
if ($callback == 'user_access') {
  $item['access'] = (count($arguments) == 1) ? user_access($arguments[0]) : user_access($arguments[0], $arguments[1]);
}
elseif (function_exists($callback)) {
  $item['access'] = call_user_func_array($callback, $arguments);
}

Код, который должен быть как можно более универсальным, напрямую не обрабатывает пользовательский объект. Это означает, что невозможно заменить объект пользователя для текущего пользователя, вошедшего в систему, другим объектом пользователя.
Код должен быть достаточно универсальным для обработки определений меню, таких как следующие:

$items['node/add/' . $type_url_str] = array(
  'title' => $type->name, 
  'title callback' => 'check_plain', 
  'page callback' => 'node_add', 
  'page arguments' => array($type->type), 
  'access callback' => 'node_access', 
  'access arguments' => array('create', $type->type), 
  'description' => $type->description, 
  'file' => 'node.pages.inc',
);

$items['node/%node'] = array(
  'title callback' => 'node_page_title', 
  'title arguments' => array(1),
  // The page callback also invokes drupal_set_title() in case
  // the menu router's title is overridden by a menu link. 
  'page callback' => 'node_page_view', 
  'page arguments' => array(1), 
  'access callback' => 'node_access', 
  'access arguments' => array('view', 1),
);

В обоих определениях аргументы доступа не включают объект пользователя, и в этом случае node_access () использует объект пользователя для текущего пользователя, вошедшего в систему. Во втором случае одним из аргументов является объект узла, полученный из URL; например, если URL-адрес example.com/node/1, то второй аргумент, переданный обратному вызову доступа, является объектом узла для узла с идентификатором узла, равным 1.
Написание кода, который обрабатывает эти случаи, также будет означать дублирование кода уже существует в Drupal. Даже если вы продублировали этот код, все равно будет проблема обратных вызовов доступа, которые проверяют доступ по отношению к вошедшему в данный момент пользователю.

Если вы хотите проверить, может ли пользователь, не являющийся в данный момент вошедшим в систему пользователем, получить доступ к меню, сначала измените значение глобальной переменной $user, используйте код, который я сообщил в начале моего ответа, а затем восстановите значение $user, Чтобы узнать, как изменить значение global $user, вы можете увидеть, как программно выдает себя за другого пользователя, не вызывая текущего пользователя, вошедшего в систему . Разница в том, что вместо использования значения, возвращаемого от drupal_anonymous_user () , вы используете значение, возвращаемое из user_load () .

киамалуно
источник
Могу ли я узнать, в какой хук этот код должен быть написан.
Гладиатор
14

Попробуйте drupal_valid_path () .

Функция возвращает TRUEпуть, переданный в качестве аргумента, и текущий пользователь имеет к нему доступ. Итак, если вы работаете над Drupal 7 и вам нужно проверить доступ к текущему вошедшему в систему пользователю, это самый простой способ:

if (drupal_valid_path('my/path')) {
  // Your code here...
}
peterpoe
источник
1
В D7 drupal_valid_pathотлично справляется со своей задачей и делает это именно для этого. Он использует menu_get_item и также проверяет доступ.
Weboide
Это правда, но это работает только для текущего пользователя. Если вы хотите узнать, может ли какой-либо другой пользователь получить доступ к пути, вам drupal_valid_pathэто не поможет.
Эндрю Шульман
@ AndrewSchulman Не думаю, что для этого есть API, но вы можете временно переключать пользователей.
peterpoe
В Drupal 8 это переместилось \Drupal::service('path.validator')->isValid($path);- см. Документацию
Gogowitsch
3

Вызовите тот, access callbackкоторый указан в пункте меню, который отвечает за страницу. Этот пункт меню обычно создается Drupal, вызывающим реализацию, hook_menuи сохраняется где-то в базе данных. Помните, что возвращаемые данные hook_menuмогут быть изменены модулем реализации hook_menu_alter.

Помните, что некоторые модули могут не передавать пользователя в качестве отдельного аргумента (как указано access argumentsключом пункта меню), но вместо этого могут использовать глобальный $userобъект. Вы должны будете проверить это для каждого модуля, который вы используете.

Освальд
источник
Этот метод может использоваться, чтобы узнать, разрешен ли доступ к странице другому пользователю, кроме действующего пользователя.
Освальд
1
Вызов обратного вызова доступа не так прост, как вызов любой другой функции, так как обратный вызов доступа требует определенных аргументов; смотрите _menu_check_access () , которая является функцией, которая проверяет, есть ли у текущего вошедшего в систему пользователя доступ к меню.
kiamlaluno
2

Проверьте user_access()функцию. Смотрите ссылку на указанные параметры для каждой версии Drupal. Со страницы документации для Drupal 7-8:

параметры

$ string Разрешение, такое как «администрировать узлы», проверяется на наличие.

$ account (необязательно) Аккаунт, который нужно проверить, если не указан, использовать вошедшего в систему пользователя.

Возвращаемое значение

Boolean TRUE, если текущий пользователь имеет запрошенное разрешение.

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

Laxman13
источник
user_access () предназначен для проверки, имеет ли пользователь определенный «тип» разрешений. Что нужно, если пользователь может получить доступ к определенному «пути»; например, если пользователь может получить доступ к «узлу / 12»?
Фарзан
Ну как вы определяете, когда у пользователя есть разрешение или нет? Я бы предположил, что на странице разрешений есть опция, которую вы либо проверили, либо нет, чтобы разрешить определенные роли
Laxman13
user_access()не всегда обратный вызов доступа, используемый меню; даже если бы это было так, вы должны знать аргументы доступа, которые вам нужно передать user_access().
kiamlaluno
Я знаю, что это не всегда user_access(), просто решил, что у ОП есть разрешение проверить, есть ли у пользователя доступ. Не очень описательный вопрос
Laxman13
Несмотря на то, что user_access не может проверить доступ к определенному пути, я думаю, что использование user_access всегда, когда это возможно, лучший способ проверить доступ. Хороший ответ @ Laxman13 +1.
AyeshK
2

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

Если вы хотите выяснить, может ли пользователь получить доступ к произвольному пути, который определен реализацией hook_menu (), вам, возможно, придется извлечь пункт меню из базы данных и оценить его параметр «обратный вызов доступа».

gapple
источник
2
    $node = node_load(123);

    $account = user_load(456);

    if (node_access("update", $node, $account) === TRUE) 
   {

         print "access";    
    }
Махапал Пурохит
источник