Magento web API 区分三种不同的用户类型: > **Guest**: 能够访问 `anonymous` 资源 ```xml <resources> <resource ref="anonymous" /> </resources> ``` > **Customer**: 能够访问 `self` 类型的资源 ```xml <resources> <resource ref="self"/> </resources> ``` > **Integrator: **能够访问 `acl.xml` 中定义好的特定资源 ```xml <resources> <resource ref="Magento_Cms::save"" /> </resources> ``` <br />为了更好的理解上面的内容,我们需要理解 `<VendorName>/<ModuleName>/acl.xml` 和 `<VendorName>/<ModuleName>/webapi.xml` 的关联关系,我们在 `acl.xml` 中定义对应的资源访问权限,下面的内容是 <MAGENTO_DIR>/module-cms/etc/acl.xml 中的代码: ```xml <config> <acl> <resources> <resource id="Magento_Backend::admin"> <resource id="Magento_Backend::content"> <resource id="Magento_Backend::content_elements"> <resource id="Magento_Cms::page" title="Pages"> <resource id="Magento_Cms::save" title="Save Page"/> </resource> </resource> </resource> </resource> </resources> </acl> </config> ``` 我们重点关注这里的 `Magento_Cms::save` 资源,Magento 将单个 `acl.xml` 文件合并成一个大的 ACL 树形结构,我们能在 Magento 后台的两个地方看到这个树形结构: > - Role Resource tab of the System | Permissions | User Roles | Edit | Add New Role screen > - The API tab of the System | Extensions | Integrations | Edit | Add New Integration screen: <br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1260804/1594944046775-94b5fa66-5c32-40d9-affd-85d4b0e5aa7d.png#align=left&display=inline&height=454&margin=%5Bobject%20Object%5D&name=image.png&originHeight=584&originWidth=541&size=148450&status=done&style=none&width=421)<br />在这两个地方我们可以为管理员和特殊的 web API 集成用户设定访问权限。这并不是说标准的管理员没法执行 WEB API,在鉴权类型的章节部分我们能看到他们的差别还是很明显的。<br /> <br />这些资源自给并不做任何事情,仅仅在 `acl.xml` 文件中定义他们并不会使 CMS 页面受到保护。 这里需要控制器介入,作为访问控制的一种机制。搜索 `Magento_Cms::save` 字符能看到在 `Magento\Cms\Controller\Adminhtml\Page\Edit` 类中定义了 `const ADMIN_RESOURCE = 'Magento_Cms::save'` 。<br /> <br /> 常量 `ADMIN_RESOURCE` 的定义是在基类 `\Magento\Backend\App\AbstractAction` 中定义的,默认是 `const ADMIN_RESOURCE = 'Magento_Backend::admin'` ,该值在 `_isAllowed` 中的使用情况如下: ```xml protected function _isAllowed() { return $this->_authorization->isAllowed(static::ADMIN_RESOURCE); } ``` 这里的 `AbstractAction` 类是 Magento 中其他很多 admin 控制器的基类,这也意味着控制器才是真正利用 `acl.xml` 文件中定义的资源的类。`acl.xml` 文件的主要目的是创建 ACL 树形结构。这意味着任何一个人如果要访问后台的 `cms/page/edit` ,它必须拥有 `Magento_Cms::save` 的访问权限。否则,`_isAllowed` 方法在读取到 `ADMIN_RESOURCE` 后会返回 `false` 并拒绝对应 URL 的访问。<br /> <br />对于 Web APIs,它不适用控制器,也就没有对应的 `ADMIN_RESOURCE` 常量和 `_isAllowed` 方法,API 使用 `webapi.xml` 类定义 `routes` ,一起来看看 `<MAGENTO_DIR>/module-cms/etc/webapi.xml` 文件中 CMS 页面保存相关的部分: ```xml <routes> <route url="/V1/cmsPage" method="POST"> <service class="Magento\Cms\Api\PageRepositoryInterface" method="save"/> <resources> <resource ref="Magento_Cms::page"/> </resources> </route> <route url="/V1/cmsPage/:id" method="PUT"> <service class="Magento\Cms\Api\PageRepositoryInterface" method="save"/> <resources> <resource ref="Magento_Cms::page"/> </resources> </route> </routes> ``` 上面的路由定义将下面的几部分绑定在了一起,`url` 和 `method` 参数指定了那个 URL 会触发这个 `route` ,`service` 元素中的 `class` 和 `method` 参数指定了当路由被触发时要执行的接口和方法。最后 `resource` 标签中的 `ref` 指定了要执行的安全性检查针对的是哪一个资源。如果一个用户执行一个未经授权的 web API 请求,或者它不是一个拥有 `Magento_Cms::page` 资源的角色,对应的请求就不会执行到上面指定的方法。 customer 类型的用户适合使用 widgets,Magento 的结算页面就是一个很好的例子。整个结算就是一个完全使用 Ajax 的应用,这和普通的前台界面比如 CMS、分类和产品页面不同。