菜单已经显示,点击却 Access denied,说明路由大概率是通的,问题落在 ACL:菜单 resource、Controller 的 ADMIN_RESOURCE 和 acl.xml 没指向同一个 ID。

把三个resource ID并排对照

etc/adminhtml/menu.xml:

<add id="Vendor_Module::records"
     title="Records"
     module="Vendor_Module"
     sortOrder="20"
     parent="Magento_Backend::content"
     action="vendor_module/record/index"
     resource="Vendor_Module::records"/>

Controller:

class Index extends MagentoBackendAppAction
{
    public const ADMIN_RESOURCE = 'Vendor_Module::records';
}

etc/acl.xml 中也必须存在完全相同的 ID,并挂在合适的父资源下。大小写、下划线和模块前缀只要有一个字符不同,管理员就会被拒绝。

超级管理员能进,普通角色不能进,就刷新角色资源

修改 ACL 后执行:

php bin/magento cache:clean config

然后在后台重新保存一次角色权限,让新 resource 写入角色规则。不要直接修改 authorization_rule 表,因为层级变化后很容易留下错误授权。

用两个账号验证:超级管理员应能访问,受限角色只有勾选 Records 后才能访问;取消权限后再次请求应返回 Access denied。这样既证明功能可用,也证明 ACL 没被为了省事设置成过宽的父级资源。