Compruebe si el usuario tiene acceso a cierta página

23

¿Cómo puedo determinar si un usuario tiene permiso para acceder a cierta página?

farzan
fuente
No especificó qué versión de Drupal usa. Más detalles sobre su objetivo también serían útiles; En los casos más comunes, Drupal gestionará el acceso al menú automáticamente.
Dylan Tack

Respuestas:

25

Si desea verificar si el usuario actualmente conectado tiene acceso a una página, puede usar el siguiente código:

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

$path es la ruta de la página que desea verificar (por ejemplo, nodo / 1, administrador / usuario / usuario).

El código funciona en Drupal 6 y versiones superiores, y es el que se usa desde menu_execute_active_handler () .

La razón por la que no sugiero llamar directamente a la devolución de llamada de acceso es porque los argumentos que deben pasarse a esa función.

El código utilizado por _menu_check_access () es el siguiente (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);
}

El código, que debe ser lo más genérico posible, no maneja directamente un objeto de usuario. Esto significa que no es posible reemplazar el objeto de usuario para el usuario actualmente conectado con otro objeto de usuario.
El código debe ser lo suficientemente genérico como para manejar definiciones de menú como las siguientes:

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

En ambas definiciones, los argumentos de acceso no incluyen un objeto de usuario, y node_access () en este caso usa el objeto de usuario para el usuario actualmente conectado. En el segundo caso, uno de los argumentos es el objeto de nodo que se obtiene de la URL; por ejemplo, si la URL es example.com/node/1, entonces el segundo argumento pasado a la devolución de llamada de acceso es el objeto de nodo para el nodo con ID de nodo igual a 1.
Escribir código que maneja estos casos también significaría duplicar código ya existente en Drupal. Incluso si ha duplicado ese código, aún existiría el problema de las devoluciones de llamada de acceso que verifican el acceso con el usuario actualmente conectado.

Si desea verificar si un usuario que no es el usuario actualmente conectado puede acceder a un menú, primero debe cambiar el valor de la variable global $user, usar el código que informé al comienzo de mi respuesta y luego restaurar el valor de $user. Para $usersaber cómo cambiar el valor de global , puede ver que se hace pasar por otro usuario de manera programática sin que el usuario actualmente conectado cierre sesión . La diferencia es que, en lugar de usar el valor devuelto por drupal_anonymous_user () , usa el valor devuelto por user_load () .

kiamlaluno
fuente
¿Puedo saber en qué gancho se debe escribir este código?
Gladiador
14

Prueba drupal_valid_path () .

La función devuelve TRUEes la ruta pasada como argumento existe y el usuario actual tiene acceso a ella. Entonces, si está trabajando en Drupal 7 y necesita verificar el acceso del usuario actualmente conectado, es la forma más fácil de hacerlo:

if (drupal_valid_path('my/path')) {
  // Your code here...
}
Peterpoe
fuente
1
En D7, drupal_valid_pathhace el trabajo perfectamente y está hecho para satisfacer esta necesidad exacta. Utiliza menu_get_item y comprueba el acceso también.
Weboide
Eso es cierto, pero solo funciona para el usuario actualmente conectado. Si desea saber si algún otro usuario puede acceder a la ruta, drupal_valid_pathno lo ayudará.
Andrew Schulman
@ AndrewSchulman No creo que haya una API para eso, pero puedes cambiar de usuario temporalmente.
Peterpoe
En Drupal 8, esto se ha movido a \Drupal::service('path.validator')->isValid($path);- vea la documentación de
Gogowitsch
3

Llame al access callbackque se especifica en la entrada del menú responsable de la página. Esa entrada de menú generalmente es creada por Drupal llamando a la implementación de hook_menuy se almacena en algún lugar de la base de datos. Tenga en cuenta que los datos devueltos hook_menupueden ser modificados por la implementación de un módulo hook_menu_alter.

Tenga en cuenta que algunos módulos pueden no pasar al usuario como un argumento separado (como se especifica en la access argumentstecla de la entrada del menú), sino que pueden usar el $userobjeto global . Deberá verificar esto para cada módulo que utilice.

Oswald
fuente
Este método se puede utilizar para averiguar si otro usuario que no sea el usuario activo puede acceder a la página.
Oswald
1
Llamar a la devolución de llamada de acceso no es tan fácil como llamar a cualquier otra función, ya que la devolución de llamada de acceso necesita argumentos específicos; vea _menu_check_access () , que es la función que verifica si el usuario actualmente conectado tiene acceso a un menú.
kiamlaluno
2

Echa un vistazo a la user_access()función. Vea el enlace para los parámetros especificados para cada versión de Drupal. Desde la página de documentación de Drupal 7-8:

Parámetros

$ string El permiso, como "administrar nodos", que se está buscando.

$ cuenta (opcional) La cuenta a verificar, si no se le da uso al usuario actualmente conectado.

Valor de retorno

Boolean TRUE si el usuario actual tiene el permiso solicitado.

Todas las verificaciones de permisos en Drupal deben pasar por esta función. De esta manera, garantizamos un comportamiento constante y nos aseguramos de que el superusuario pueda realizar todas las acciones.

Laxman13
fuente
user_access () es para verificar si el usuario tiene un cierto "tipo" de permisos. Lo que se necesita es si el usuario puede acceder a una determinada "ruta"; por ejemplo, si el usuario puede acceder a 'nodo / 12'?
farzan
Bueno, ¿cómo estás determinando cuándo un usuario tiene permiso o no? Supongo que hay una opción en la página de permisos que ha marcado o no para dar permiso a ciertos roles
Laxman13
user_access()no siempre es la devolución de llamada de acceso utilizada por un menú; incluso lo sería, debe conocer los argumentos de acceso a los que debe pasar user_access().
kiamlaluno
Sé que no siempre es así user_access(), solo pensé que el OP tenía un permiso en mente para verificar si el usuario debería tener acceso. No es una pregunta muy descriptiva
Laxman13
Aunque user_access no puede verificar el acceso a una ruta específica, creo que usar user_access siempre que sea posible es la mejor manera de verificar el acceso. Buena respuesta @ Laxman13 +1.
AyeshK
2

Si necesita saber si un usuario puede acceder a un nodo en particular y está utilizando un módulo de acceso de nodo, puede usar node_access () . (sin un módulo de acceso de nodo solo necesitan el permiso de 'contenido de acceso').

Si desea averiguar si un usuario puede acceder a una ruta arbitraria definida por una implementación hook_menu (), puede que tenga que recuperar la entrada del menú de la base de datos y evaluar su parámetro de 'devolución de llamada de acceso'.

hueco
fuente
2
    $node = node_load(123);

    $account = user_load(456);

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

         print "access";    
    }
Mahipal Purohit
fuente