检查用户是否有权访问特定页面


23

如何确定用户是否有权访问某个页面?


您没有指定使用哪个版本的Drupal。有关目标的更多详细信息也将很有用;在最常见的情况下,Drupal将自动处理菜单访问。
Dylan Tack

Answers:


25

如果要验证当前登录的用户是否有权访问页面,可以使用以下代码:

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

$path 是您要检查的页面的路径(例如,node / 1,admin / user / user)。

该代码可在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,则传递给访问回调的第二个参数是节点ID等于1的节点的节点对象。
编写处理这些情况的代码也将意味着重复代码。在Drupal中已经存在。即使您重复了该代码,访问回调仍存在问题,即正在根据当前登录的用户检查访问。

如果要检查不是当前登录用户的用户是否可以访问菜单,请首先更改全局变量的值$user,然后使用我在答案开头报告的代码,然后恢复的值。$user。有关如何更改全局值的信息$user,请参见以编程方式模拟其他用户而不会导致当前登录的用户注销。区别在于,不是使用drupal_anonymous_user()返回的值,而是使用user_load()返回的值。


我可以知道该代码应该写在哪个钩子上。
角斗士

14

尝试drupal_valid_path()

该函数返回的TRUE是存在参数时传递的路径,当前用户可以访问该路径。因此,如果您正在使用Drupal 7,并且需要检查当前登录用户的访问权限,那么这是最简单的方法:

if (drupal_valid_path('my/path')) {
  // Your code here...
}

1
在D7中,drupal_valid_path可以完美地完成工作,并且可以满足这一确切需求。它使用menu_get_item并检查访问。
Weboide 2014年

是的,但这仅适用于当前登录的用户。如果您想知道其他用户是否可以访问该路径,drupal_valid_path将无济于事。
安德鲁·舒尔曼

@AndrewSchulman我认为没有API,但是您可以临时切换用户。
peterpoe

在Drupal 8中,它已移至\Drupal::service('path.validator')->isValid($path);-参见API文档
-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(可选)要检查的帐户(如果未使用当前登录的用户)。

返回值

布尔值TRUE(如果当前用户具有所请求的权限)。

Drupal中的所有权限检查都应通过此功能。这样,我们保证行为一致,并确保超级用户可以执行所有操作。


user_access()用于检查用户是否具有某种“类型”的权限。需要的是用户是否可以访问某个“路径”;例如,用户是否可以访问“ node / 12”?
赞2011年

那么,您如何确定用户何时获得许可?我认为权限页面上有一个选项,您已经检查或不授予某些角色该权限
Laxman13 2011年

user_access()并不总是菜单使用的访问回调;即使是这样,您也应该知道需要传递给的访问参数user_access()
kiamlaluno

我知道这并不总是这样user_access(),只是想出OP有权限检查用户是否应该具有访问权限。这不是一个描述性很强的问题
Laxman13,2011年

即使user_access无法检查对特定路径的访问,我认为只要有可能就使用user_access是检查访问的最佳方法。好答案@ Laxman13 +1。
AyeshK 2013年

2

如果需要知道用户是否可以访问特定节点并且正在使用节点访问模块,则可以使用node_access()。(没有节点访问模块,他们只需要“访问内容”权限。)

如果要确定用户是否可以访问由hook_menu()实现定义的任意路径,则可能必须从数据库中检索菜单项并评估其“访问回调”参数。


2
    $node = node_load(123);

    $account = user_load(456);

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

         print "access";    
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.