Vérifiez si l'utilisateur a accès à une certaine page

23

Comment puis-je déterminer si un utilisateur est autorisé à accéder à une certaine page?

farzan
la source
Vous n'avez pas spécifié la version de Drupal que vous utilisez. Plus de détails sur votre objectif seraient également utiles; dans les cas les plus courants, Drupal gère automatiquement l'accès au menu.
Dylan Tack

Réponses:

25

Si vous souhaitez vérifier si l'utilisateur actuellement connecté a accès à une page, vous pouvez utiliser le code suivant:

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

$path est le chemin de la page que vous souhaitez vérifier (par exemple, node / 1, admin / user / user).

Le code fonctionne dans Drupal 6 et les versions supérieures, et c'est celui utilisé à partir de menu_execute_active_handler () .

La raison pour laquelle je ne suggère pas d'appeler directement le rappel d'accès est parce que les arguments qui doivent être passés à cette fonction.

Le code utilisé par _menu_check_access () est le suivant (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);
}

Le code, qui doit être aussi générique que possible, ne gère pas directement un objet utilisateur. Cela signifie qu'il n'est pas possible de remplacer l'objet utilisateur pour l'utilisateur actuellement connecté par un autre objet utilisateur.
Le code doit être suffisamment générique pour gérer les définitions de menu telles que les suivantes:

$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),
);

Dans les deux définitions, les arguments d'accès n'incluent pas d'objet utilisateur et node_access () dans ce cas utilise l'objet utilisateur pour l'utilisateur actuellement connecté. Dans le second cas, l'un des arguments est l'objet nœud obtenu à partir de l'URL; par exemple, si l'URL est example.com/node/1, le deuxième argument transmis au rappel d'accès est l'objet nœud pour le nœud avec l'ID nœud égal à 1.
L'écriture de code qui gère également ces cas signifierait dupliquer le code déjà existant dans Drupal. Même si vous avez dupliqué ce code, il y aurait toujours le problème des rappels d'accès qui vérifient l'accès par rapport à l'utilisateur actuellement connecté.

Si vous souhaitez vérifier si un utilisateur qui n'est pas l'utilisateur actuellement connecté peut accéder à un menu, modifiez d'abord la valeur de la variable globale $user, utilisez le code que j'ai signalé au début de ma réponse, puis restaurez la valeur de $user. Pour savoir comment modifier la valeur du global $user, vous pouvez voir Emprunter l'identité d'un autre utilisateur par programme sans entraîner la déconnexion de l'utilisateur actuellement connecté . La différence est qu'au lieu d'utiliser la valeur renvoyée par drupal_anonymous_user () , vous utilisez la valeur renvoyée par user_load () .

kiamlaluno
la source
Puis-je savoir dans quel crochet ce code doit être écrit.
Gladiator le
14

Essayez drupal_valid_path () .

La fonction retourne TRUEest le chemin d'accès passé car l'argument existe et l'utilisateur actuel y a accès. Donc, si vous travaillez sur Drupal 7 et que vous devez vérifier l'accès sur l'utilisateur actuellement connecté, c'est la façon la plus simple de procéder:

if (drupal_valid_path('my/path')) {
  // Your code here...
}
peterpoe
la source
1
En D7, drupal_valid_pathfait parfaitement le travail et est fait pour répondre à ce besoin précis. Il utilise menu_get_item et vérifie également l'accès.
Weboide
C'est vrai, mais cela ne fonctionne que pour l'utilisateur actuellement connecté. Si vous voulez savoir si un autre utilisateur peut accéder au chemin, drupal_valid_pathcela ne vous aidera pas.
Andrew Schulman
@AndrewSchulman Je ne pense pas qu'il existe une API pour cela, mais vous pouvez temporairement changer d'utilisateur.
peterpoe
Dans Drupal 8, cela est passé à \Drupal::service('path.validator')->isValid($path);- voir la documentation de
Gogowitsch
3

Appelez le access callbackqui est spécifié dans l'entrée de menu qui est responsable de la page. Cette entrée de menu est généralement créée par Drupal appelant l'implémentation de hook_menuet est stockée quelque part dans la base de données. Attention, les données renvoyées par hook_menupeuvent être modifiées par un module implémentant hook_menu_alter.

Attention, certains modules peuvent ne pas passer l'utilisateur comme un argument séparé (comme spécifié par la access argumentsclé de l'entrée de menu), mais peuvent utiliser à la $userplace l'objet global . Vous devrez vérifier cela pour chaque module que vous utilisez.

Oswald
la source
Cette méthode peut être utilisée pour savoir si un autre utilisateur que l'utilisateur actif est autorisé à accéder à la page.
Oswald
1
L'appel du rappel d'accès n'est pas aussi simple que d'appeler n'importe quelle autre fonction, car le rappel d'accès nécessite des arguments spécifiques; voir _menu_check_access () , qui est la fonction qui vérifie si l'utilisateur actuellement connecté a accès à un menu.
kiamlaluno
2

Découvrez la user_access()fonction. Voir le lien pour les paramètres spécifiés pour chaque version de Drupal. Depuis la page de documentation de Drupal 7-8:

Paramètres

$ string L'autorisation, telle que "administrer les nœuds", est en cours de vérification.

$ account (facultatif) Le compte à vérifier, s'il n'est pas indiqué, l'utilisateur actuellement connecté.

Valeur de retour

Boolean TRUE si l'utilisateur actuel a l'autorisation demandée.

Tous les contrôles d'autorisation dans Drupal doivent passer par cette fonction. De cette façon, nous garantissons un comportement cohérent et garantissons que le superutilisateur peut effectuer toutes les actions.

Laxman13
la source
user_access () sert à vérifier si l'utilisateur a un certain "type" d'autorisations. Ce qui est nécessaire, c'est si l'utilisateur peut accéder à un certain "chemin"; par exemple, si l'utilisateur peut accéder à 'node / 12'?
farzan
Eh bien, comment déterminez-vous quand un utilisateur a l'autorisation ou non? Je suppose qu'il y a une option sur la page des autorisations que vous avez vérifiée ou non pour donner l'autorisation à certains rôles
Laxman13
user_access()n'est pas toujours le rappel d'accès utilisé par un menu; même si c'est le cas, vous devez connaître les arguments d'accès que vous devez transmettre user_access().
kiamlaluno
Je sais que ce n'est pas toujours user_access(), je pensais juste que l'OP avait une permission à l'esprit pour vérifier si l'utilisateur devrait y avoir accès. Pas une question très descriptive
Laxman13
Même si user_access ne peut pas vérifier l'accès à un chemin spécifique, je pense que l'utilisation de user_access autant que possible est la meilleure façon de vérifier l'accès. Bonne réponse @ Laxman13 +1.
AyeshK
2

Si vous avez besoin de savoir si un utilisateur peut accéder à un nœud particulier et utilise un module d'accès au nœud, vous pouvez utiliser node_access () . (sans module d'accès aux nœuds, ils ont juste besoin de l'autorisation «accéder au contenu».)

Si vous souhaitez déterminer si un utilisateur peut accéder à un chemin arbitraire défini par une implémentation hook_menu (), vous devrez peut-être récupérer l'entrée de menu de la base de données et évaluer son paramètre 'access callback'.

gapple
la source
2
    $node = node_load(123);

    $account = user_load(456);

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

         print "access";    
    }
Mahipal Purohit
la source