[TOC]
# 訪問控制列表(ACL)
`Phalcon\Acl` 提供簡單輕量級的ACL管理以及附加的權限。[訪問控制列表](http://en.wikipedia.org/wiki/Access_control_list)(ACL)允許應用程序控制對其區域和來自請求的底層對象的訪問。建議您閱讀有關ACL方法的更多信息,以便熟悉其概念。
總之,ACL具有角色和資源。資源是遵守ACL為其定義的權限的對象。角色是請求訪問資源的對象,ACL機制可以允許或拒絕訪問。
## 創建ACL
該組件最初用于內存。這提供了易用性和訪問列表的每個方面的速度。`Phalcon\Acl` 構造函數將第一個參數作為用于檢索與控制列表相關的信息的適配器。使用內存適配器的示例如下:
```php
<?php
use Phalcon\Acl\Adapter\Memory as AclList;
$acl = new AclList();
```
默認情況下, `Phalcon\Acl` 允許訪問尚未定義的資源。為了提高訪問列表的安全級別,我們可以將拒絕級別定義為默認訪問級別。
```php
<?php
use Phalcon\Acl;
// Default action is deny access
$acl->setDefaultAction(
Acl::DENY
);
```
## 將角色添加到ACL
角色是可以或不可以訪問訪問列表中的某些資源的對象。例如,我們將角色定義為組織中的人員組。`Phalcon\Acl\Role` 類可用于以更結構化的方式創建角色。讓我們在最近創建的列表中添加一些角色:
```php
<?php
use Phalcon\Acl\Role;
// Create some roles.
// The first parameter is the name, the second parameter is an optional description.
$roleAdmins = new Role('Administrators', 'Super-User role');
$roleGuests = new Role('Guests');
// Add 'Guests' role to ACL
$acl->addRole($roleGuests);
// Add 'Designers' role to ACL without a Phalcon\Acl\Role
$acl->addRole('Designers');
```
如您所見,角色是直接定義的,不使用實例。
## 添加資源
資源是控制訪問的對象。通常在MVC應用程序中,資源是指控制器。雖然這不是強制性的,但 `Phalcon\Acl\Resource` 類可用于定義資源。將相關操作或操作添加到資源非常重要,這樣ACL才能理解應該控制的內容。
```php
<?php
use Phalcon\Acl\Resource;
// Define the 'Customers' resource
$customersResource = new Resource('Customers');
// Add 'customers' resource with a couple of operations
$acl->addResource(
$customersResource,
'search'
);
$acl->addResource(
$customersResource,
[
'create',
'update',
]
);
```
## 定義訪問控制
現在我們有角色和資源,是時候定義ACL(即哪些角色可以訪問哪些資源)。這部分非常重要,特別是考慮到您的默認訪問級別`allow`或`deny`。
```php
<?php
// Set access level for roles into resources
$acl->allow('Guests', 'Customers', 'search');
$acl->allow('Guests', 'Customers', 'create');
$acl->deny('Guests', 'Customers', 'update');
```
`allow()`方法指定特定角色已授予對特定資源的訪問權限。 `deny()` 方法恰恰相反。
## 查詢ACL
列表完全定義后。我們可以查詢它以檢查角色是否具有給定的權限。
```php
<?php
// Check whether role has access to the operations
// Returns 0
$acl->isAllowed('Guests', 'Customers', 'edit');
// Returns 1
$acl->isAllowed('Guests', 'Customers', 'search');
// Returns 1
$acl->isAllowed('Guests', 'Customers', 'create');
```
## 基于功能的訪問
您還可以添加自定義函數作為第4個參數,該函數必須返回布爾值。使用`isAllowed()`方法時將調用它。您可以將參數作為關聯數組傳遞給`isAllowed()`方法作為第4個參數,其中key是我們定義的函數中的參數名稱。
```php
<?php
// Set access level for role into resources with custom function
$acl->allow(
'Guests',
'Customers',
'search',
function ($a) {
return $a % 2 === 0;
}
);
// Check whether role has access to the operation with custom function
// Returns true
$acl->isAllowed(
'Guests',
'Customers',
'search',
[
'a' => 4,
]
);
// Returns false
$acl->isAllowed(
'Guests',
'Customers',
'search',
[
'a' => 3,
]
);
```
此外,如果您未在`isAllowed()`方法中提供任何參數,則默認行為將為`Acl::ALLOW`。您可以使用方法`setNoArgumentsDefaultAction()`更改它。
```php
<?php
use Phalcon\Acl;
// Set access level for role into resources with custom function
$acl->allow(
'Guests',
'Customers',
'search',
function ($a) {
return $a % 2 === 0;
}
);
// Check whether role has access to the operation with custom function
// Returns true
$acl->isAllowed(
'Guests',
'Customers',
'search'
);
// Change no arguments default action
$acl->setNoArgumentsDefaultAction(
Acl::DENY
);
// Returns false
$acl->isAllowed(
'Guests',
'Customers',
'search'
);
```
## 對象作為角色名稱和資源名稱
您可以將對象作為`roleName`和`resourceName`傳遞。您的類必須為`roleName`實現`Phalcon\Acl\RoleAware`,為`resourceName`實現`Phalcon\Acl\ResourceAware`。
我們的 `UserRole` 類
```php
<?php
use Phalcon\Acl\RoleAware;
// Create our class which will be used as roleName
class UserRole implements RoleAware
{
protected $id;
protected $roleName;
public function __construct($id, $roleName)
{
$this->id = $id;
$this->roleName = $roleName;
}
public function getId()
{
return $this->id;
}
// Implemented function from RoleAware Interface
public function getRoleName()
{
return $this->roleName;
}
}
```
我們的 `ModelResource` 類
```php
<?php
use Phalcon\Acl\ResourceAware;
// Create our class which will be used as resourceName
class ModelResource implements ResourceAware
{
protected $id;
protected $resourceName;
protected $userId;
public function __construct($id, $resourceName, $userId)
{
$this->id = $id;
$this->resourceName = $resourceName;
$this->userId = $userId;
}
public function getId()
{
return $this->id;
}
public function getUserId()
{
return $this->userId;
}
// Implemented function from ResourceAware Interface
public function getResourceName()
{
return $this->resourceName;
}
}
```
然后你可以在`isAllowed()`方法中使用它們。
```php
<?php
use UserRole;
use ModelResource;
// Set access level for role into resources
$acl->allow('Guests', 'Customers', 'search');
$acl->allow('Guests', 'Customers', 'create');
$acl->deny('Guests', 'Customers', 'update');
// Create our objects providing roleName and resourceName
$customer = new ModelResource(
1,
'Customers',
2
);
$designer = new UserRole(
1,
'Designers'
);
$guest = new UserRole(
2,
'Guests'
);
$anotherGuest = new UserRole(
3,
'Guests'
);
// Check whether our user objects have access to the operation on model object
// Returns false
$acl->isAllowed(
$designer,
$customer,
'search'
);
// Returns true
$acl->isAllowed(
$guest,
$customer,
'search'
);
// Returns true
$acl->isAllowed(
$anotherGuest,
$customer,
'search'
);
```
您還可以在`allow()`或 `deny()`中訪問自定義函數中的這些對象。它們按函數類型自動綁定到參數。
```php
<?php
use UserRole;
use ModelResource;
// Set access level for role into resources with custom function
$acl->allow(
'Guests',
'Customers',
'search',
function (UserRole $user, ModelResource $model) { // User and Model classes are necessary
return $user->getId == $model->getUserId();
}
);
$acl->allow(
'Guests',
'Customers',
'create'
);
$acl->deny(
'Guests',
'Customers',
'update'
);
// Create our objects providing roleName and resourceName
$customer = new ModelResource(
1,
'Customers',
2
);
$designer = new UserRole(
1,
'Designers'
);
$guest = new UserRole(
2,
'Guests'
);
$anotherGuest = new UserRole(
3,
'Guests'
);
// Check whether our user objects have access to the operation on model object
// Returns false
$acl->isAllowed(
$designer,
$customer,
'search'
);
// Returns true
$acl->isAllowed(
$guest,
$customer,
'search'
);
// Returns false
$acl->isAllowed(
$anotherGuest,
$customer,
'search'
);
```
您仍然可以在函數中添加任何自定義參數,并在`isAllowed()`方法中傳遞關聯數組。訂單也無所謂。
## 角色繼承
您可以使用`Phalcon\Acl\Role`提供的繼承來構建復雜的角色結構。角色可以從其他角色繼承,從而允許訪問超集或資源子集。要使用角色繼承,在列表中添加該角色時,需要將繼承的角色作為方法調用的第二個參數傳遞。
```php
<?php
use Phalcon\Acl\Role;
// ...
// Create some roles
$roleAdmins = new Role('Administrators', 'Super-User role');
$roleGuests = new Role('Guests');
// Add 'Guests' role to ACL
$acl->addRole($roleGuests);
// Add 'Administrators' role inheriting from 'Guests' its accesses
$acl->addRole($roleAdmins, $roleGuests);
```
## 序列化ACL列表
為了提高性能,可以將 `Phalcon\Acl` 實例序列化并存儲在APC,會話,文本文件或數據庫表中,以便可以隨意加載它們,而無需重新定義整個列表。你可以這樣做:
```php
<?php
use Phalcon\Acl\Adapter\Memory as AclList;
// ...
// Check whether ACL data already exist
if (!is_file('app/security/acl.data')) {
$acl = new AclList();
// ... Define roles, resources, access, etc
// Store serialized list into plain file
file_put_contents(
'app/security/acl.data',
serialize($acl)
);
} else {
// Restore ACL object from serialized file
$acl = unserialize(
file_get_contents('app/security/acl.data')
);
}
// Use ACL list as needed
if ($acl->isAllowed('Guests', 'Customers', 'edit')) {
echo 'Access granted!';
} else {
echo 'Access denied :(';
}
```
建議在開發期間使用Memory適配器,并在生產中使用其他適配器之一。
## 事件
`Phalcon\Acl` 能夠將事件發送到`EventsManager`(如果存在)。使用“acl”類型觸發事件。返回布爾值false時的某些事件可能會停止活動操作。支持以下事件:
| 事件名稱 | 觸發 | Can stop operation? |
| ----------------- | ------------------------------------------------------- |:-------------------:|
| beforeCheckAccess | 在檢查角色/資源是否具有訪問權限之前觸發 | Yes |
| afterCheckAccess | 在檢查角色/資源是否具有訪問權限之后觸發 | No |
以下示例演示如何將偵聽器附加到此組件:
```php
<?php
use Phalcon\Acl\Adapter\Memory as AclList;
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
// ...
// Create an event manager
$eventsManager = new EventsManager();
// Attach a listener for type 'acl'
$eventsManager->attach(
'acl:beforeCheckAccess',
function (Event $event, $acl) {
echo $acl->getActiveRole();
echo $acl->getActiveResource();
echo $acl->getActiveAccess();
}
);
$acl = new AclList();
// Setup the $acl
// ...
// Bind the eventsManager to the ACL component
$acl->setEventsManager($eventsManager);
```
## 實現自己的適配器
必須實現`Phalcon\Acl\AdapterInterface`接口才能創建自己的ACL適配器或擴展現有ACL適配器。
- 常規
- Welcome
- 貢獻
- 生成回溯
- 測試重現
- 單元測試
- 入門
- 安裝
- Web服務器設置
- WAMP
- XAMPP
- 教程
- 基礎教程
- 教程:創建一個簡單的REST API
- 教程:V?kuró
- 提升性能
- 教程:INVO
- 開發環境
- Phalcon Compose (Docker)
- Nanobox
- Phalcon Box (Vagrant)
- 開發工具
- Phalcon開發者工具的安裝
- Phalcon開發者工具的使用
- 調試應用程序
- 核心
- MVC應用
- 微應用
- 創建命令行(CLI)應用程序
- 依賴注入與服務定位
- MVC架構
- 服務
- 使用緩存提高性能
- 讀取配置
- 上下文轉義
- 類加載器
- 使用命名空間
- 日志
- 隊列
- 數據庫
- 數據庫抽象層
- Phalcon查詢語言(PHQL)
- ODM(對象文檔映射器)
- 使用模型
- 模型行為
- ORM緩存
- 模型事件
- 模型元數據
- 模型關系
- 模型事務
- 驗證模型
- 數據庫遷移
- 分頁
- 前端
- Assets管理
- 閃存消息
- 表單
- 圖像
- 視圖助手(標簽)
- 使用視圖
- Volt:模板引擎
- 業務邏輯
- 訪問控制列表(ACL)
- 注解解析器
- 控制器
- 調度控制器
- 事件管理器
- 過濾與清理
- 路由
- 在session中存儲數據
- 生成URL和路徑
- 驗證
- HTTP
- Cookies管理
- 請求環境
- 返回響應
- 安全
- 加密/解密
- 安全
- 國際化
- 國際化
- 多語言支持