如何使用 hook_menu_alter() 操作路径访问控制
/**
* Implementation of hook_menu_alter().
*/
function joke_menu_alter(&$callbacks) {
// If the user does not have 'administer nodes' permission,
// disable the joke menu item by setting its access callback to FALSE.
if (!user_access('administer nodes')) {
$callbacks['node/add/joke']['access callback'] = FALSE;
// Must unset access arguments or Drupal will use user_access()
// as a default access callback.
unset($callbacks['node/add/joke']['access arguments']);
}
}
以上功能来自drupal pro开发。我不太明白。为什么必须取消设置访问参数 (unset($callbacks['node/add/joke']['access argument']);)
?
谢谢。
/**
* Implementation of hook_menu_alter().
*/
function joke_menu_alter(&$callbacks) {
// If the user does not have 'administer nodes' permission,
// disable the joke menu item by setting its access callback to FALSE.
if (!user_access('administer nodes')) {
$callbacks['node/add/joke']['access callback'] = FALSE;
// Must unset access arguments or Drupal will use user_access()
// as a default access callback.
unset($callbacks['node/add/joke']['access arguments']);
}
}
The above function is from the pro development drupal. I can't understand it well. Why must I unset the access arguments (unset($callbacks['node/add/joke']['access arguments']);)
?
Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
整个例子看起来很糟糕而且很糟糕。简而言之,一个笑话。首先,让我回答你的问题,然后我将继续解释为什么你不应该在实践中遵循这个例子。
来自 includes/menu.inc:
当您不再需要访问回调时取消它们(毕竟现在依赖于布尔值)可以防止 Drupal 路由系统中过于聪明的逻辑在
中发生错误user_access()
只是为了让它有事可做。现在,我们来看看为什么这是糟糕的代码。
hook_menu()
和hook_menu_alter()
都在缓存清除时运行(更具体地说,当重建菜单路由系统时)。这意味着访问该站点以重建菜单的用户的权限将被硬编码到菜单路由行为中。这是一个非常糟糕且不一致的安排。如果您想根据权限阻止对路径的访问,则需要将回调更改为将测试该权限的回调。然后,当重建菜单时,它将检查每个页面加载的新回调函数,以查看是否应授予当前用户权限。
一个简单的例子可能如下所示:
现在我们有一个函数,它采用节点/添加/笑话路径并声明唯一重要的是用户是否有
管理节点
权限。当然,这比示例的明显意图要有限一些,示例是保留现有的访问控制,但也要求用户具有管理节点
权限。这也是可以修复的,但更复杂。借用 Spaces 项目的一些概念:
我们已成功将原始访问回调包装在新的访问回调中,我们可以在其中添加我们需要任何额外的逻辑。
请注意,在最后两个函数示例中,我使用了
$path
变量来保持代码简单。我还将$original_access
分离到它自己的行并首先检查它,实际上我会首先检查user_access()
因为它几乎肯定会比在原始访问回调。That entire example seems broken and bad. In short, a joke. First, let me answer your question, then I'll go on to explain why you shouldn't follow that example in practice.
From includes/menu.inc:
Unsetting the access callbacks when you no longer need them (relying on a boolean now, after all) prevents the over-clever logic in Drupal's routing system from slapping in
user_access()
just so it has something to do.Now, on to why that's bad code.
hook_menu()
andhook_menu_alter()
are both run on cache clear (more specifically when the menu routing system is rebuilt). This means that the permissions of whichever user hits the site to rebuild the menus will be hard-coded into menu routing behaviors. This is a very bad and inconsistent arrangement.If you want to block access to a path based on a permission, you need to change the callback to something that will test for that permission. Then when the menu is rebuilt, it will check the new callback function per page load to see if the current user should be granted permission.
A simple example of this might look like:
Now we have a function which takes the node/add/joke path and declares that the only thing that matters is whether or not the user has
administer nodes
permission. Of course, that's a little more limited than the apparent intentions of the example, which were to preserve the existing access controls, but also require the user to haveadminister nodes
permission.That is also fixable, but is more complicated. To borrow some concepts from the Spaces project:
We have successfully wrapped the original access callback in a new access callback, to which we can add whatever additional logic we need.
Note that in the last two function examples, I used the
$path
variable to keep the code simple. I also separated$original_access
to it's own line and had it checked first, in practice I would checkuser_access()
first as it would almost certainly be more performant than whatever happens in the original access callback.该行正上方的评论解释了它吗?
访问回调是被调用的函数(或 TRUE/FALSE),参数是传递给该函数的内容。您将回调设置为 false,因此始终拒绝对该路由器项的访问。
现在,正如评论所说,您还需要取消设置参数,否则 Drupal 仍将使用 user_access() (默认访问回调)。
The comment directly above that line explains it?
access callback is the function that is called (or TRUE/FALSE) and arguments is what is passed to that function. You are setting the callback to false and therefore always deny access to that router item.
And now, as the comment is saying, you also needto unset the arguments or Drupal will still use user_access() (The default access callback).