# 訪問控制列表 ACL(Access Control Lists ACL)
Phalcon在權限方面通過[Phalcon\\Acl](http://docs.iphalcon.cn/api/Phalcon_Acl.html)提供了一個輕量級的 ACL(訪問控制列表).[Access Control Lists](http://en.wikipedia.org/wiki/Access_control_list)(ACL) 允許系統對用戶的訪問權限進行控制,比如允許訪問某些資源而不允許訪問其它資源等。 這里我們建議開發者了解一些關于ACL的技術。
ACL有兩部分組成即角色和資源。 資源即是ACL定義的權限所依附的對象。 角色即是ACL所字義的請求者的身份,ACL決定了角色對資源的訪問權限,允許訪問或拒絕訪問。
## 創建 ACL(Creating an ACL)
這個組件起先是設計工作在內存中的, 這樣做提供了更高的訪問速度。[Phalcon\\Acl](http://docs.iphalcon.cn/api/Phalcon_Acl.html)構造器的第一個參數用于設置取得ACL的方式。 下面是使用內存適配器的例子:
~~~
<?php
use Phalcon\Acl\Adapter\Memory as AclList;
$acl = new AclList();
~~~
默認情況下[Phalcon\\Acl](http://docs.iphalcon.cn/api/Phalcon_Acl.html)允許我們訪問未定義的資源中的action,為了提高安全性, 我們設置默認訪問級別為‘拒絕’。
~~~
<?php
use Phalcon\Acl;
// 設置默認訪問級別為拒絕
$acl->setDefaultAction(
Acl::DENY
);
~~~
## 添加角色(Adding Roles to the ACL)
角色即是權限的集合體,其中定義了我們對資源的訪問權限。 例如, 我們會把一個組織內的不同的人定義為不同的角色。 The[Phalcon\\Acl\\Role](http://docs.iphalcon.cn/api/Phalcon_Acl_Role.html)類使用一種更有組織的方式來定義角色。 這里我們創建一些角色:
~~~
<?php
use Phalcon\Acl\Role;
// 創建角色
// The first parameter is the name, the second parameter is an optional description.
$roleAdmins = new Role("Administrators", "Super-User role");
$roleGuests = new Role("Guests");
// 添加 "Guests" 角色到ACL
$acl->addRole($roleGuests);
// 添加"Designers"到ACL, 僅使用此字符串。
$acl->addRole("Designers");
~~~
上面我們看到,我們可以直接使用字符串來定義角色。
## 添加資源(Adding Resources)
資源即是訪問控制要控制的對象之一。 正常情況下在mvc中資源一般是控制器。 Phalcon中我們使用[Phalcon\\Acl\\Resource](http://docs.iphalcon.cn/api/Phalcon_Acl_Resource.html)來定義資源。 非常重要的一點即是我們把相關的action或操作添加到資源中這樣ACL才知道控制什么資源。
~~~
<?php
use Phalcon\Acl\Resource;
// 定義 "Customers" 資源
$customersResource = new Resource("Customers");
// 為 "customers"資源添加一組操作
$acl->addResource(
$customersResource,
"search"
);
$acl->addResource(
$customersResource,
[
"create",
"update",
]
);
~~~
## 定義訪問控制(Defining Access Controls)
至此我們定義了角色及資源, 現在是定義ACL的時候了,即是定義角色對資源的訪問。 這個部分是極其重要的,特別是在我們設定了默認的訪問級別后。
~~~
<?php
// 設置角色對資源的訪問級別
$acl->allow("Guests", "Customers", "search");
$acl->allow("Guests", "Customers", "create");
$acl->deny("Guests", "Customers", "update");
~~~
allow()方法指定了允許角色對資源的訪問, deny()方法則反之。
## 查詢 ACL(Querying an ACL)
一旦訪問控制表定義之后, 我們就可以通過它來檢查角色是否有訪問權限了。
~~~
<?php
// 查詢角色是否有訪問權限
// Returns 0
$acl->isAllowed("Guests", "Customers", "edit");
// Returns 1
$acl->isAllowed("Guests", "Customers", "search");
// Returns 1
$acl->isAllowed("Guests", "Customers", "create");
~~~
## Function based access
Also you can add as 4th parameter your custom function which must return boolean value. It will be called when you use`isAllowed()`method. You can pass parameters as associative array to`isAllowed()`method as 4th argument where key is parameter name in our defined function.
~~~
<?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,
]
);
~~~
Also if you don’t provide any parameters in`isAllowed()`method then default behaviour will be`Acl::ALLOW`. You can change it by using method`setNoArgumentsDefaultAction()`.
~~~
use Phalcon\Acl;
<?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"
);
// Change no arguments default action
$acl->setNoArgumentsDefaultAction(
Acl::DENY
);
// Returns false
$acl->isAllowed(
"Guests",
"Customers",
"search"
);
~~~
## Objects as role name and resource name
You can pass objects as`roleName`and`resourceName`. Your classes must implement[Phalcon\\Acl\\RoleAware](http://docs.iphalcon.cn/api/Phalcon_Acl_RoleAware.html)for`roleName`and[Phalcon\\Acl\\ResourceAware](http://docs.iphalcon.cn/api/Phalcon_Acl_ResourceAware.html)for`resourceName`.
Our`UserRole`class
~~~
<?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;
}
}
~~~
And our`ModelResource`class
~~~
<?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;
}
}
~~~
Then you can use them in`isAllowed()`method.
~~~
<?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"
);
~~~
Also you can access those objects in your custom function in`allow()`or`deny()`. They are automatically bind to parameters by type in function.
~~~
<?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"
);
~~~
You can still add any custom parameters to function and pass associative array in`isAllowed()`method. Also order doesn’t matter.
## 角色繼承(Roles Inheritance)
我們可以使用[Phalcon\\Acl\\Role](http://docs.iphalcon.cn/api/Phalcon_Acl_Role.html)提供的繼承機制來構造更復雜的角色。 Phalcon中的角色可以繼承來自其它角色的 權限, 這樣就可以實現更巧妙的資源訪問控制。 如果要繼承權限用戶, 我們需要在添加角色函數的第二個參數中寫上要繼承的那個角色實例。
~~~
<?php
use Phalcon\Acl\Role;
// ...
// 創建角色
$roleAdmins = new Role("Administrators", "Super-User role");
$roleGuests = new Role("Guests");
// 添加 "Guests" 到 ACL
$acl->addRole($roleGuests);
// 使Administrators繼承Guests的訪問權限
$acl->addRole($roleAdmins, $roleGuests);
~~~
## 序列化 ACL 列表(Serializing ACL lists)
為了提高性能,[Phalcon\\Acl](http://docs.iphalcon.cn/api/Phalcon_Acl.html)的實例可以被實例化到APC, session, 文本或數據庫中, 這樣開發者就不需要重復的 定義acl了。 下面展示了如何去做:
~~~
<?php
use Phalcon\Acl\Adapter\Memory as AclList;
// ...
// 檢查ACL數據是否存在
if (!is_file("app/security/acl.data")) {
$acl = new AclList();
// ... Define roles, resources, access, etc
// 保存實例化的數據到文本文件中
file_put_contents(
"app/security/acl.data",
serialize($acl)
);
} else {
// 返序列化
$acl = unserialize(
file_get_contents("app/security/acl.data")
);
}
// 使用ACL
if ($acl->isAllowed("Guests", "Customers", "edit")) {
echo "Access granted!";
} else {
echo "Access denied :(";
}
~~~
It’s recommended to use the Memory adapter during development and use one of the other adapters in production.
## ACL 事件(ACL Events)
如果需要的話[Phalcon\\Acl](http://docs.iphalcon.cn/api/Phalcon_Acl.html)可以發送事件到[EventsManager](http://docs.iphalcon.cn/reference/events.html)。 這里我們為acl綁定事件。 其中一些事件的處理結果如果返回了false則表示正在處理的操作會被中止。 支持如下的事件:
| 事件名 | 觸發條件 | 能否中止操作 |
| --- | --- | --- |
| beforeCheckAccess | 在權限檢查之前觸發 | Yes |
| afterCheckAccess | 在權限檢查之后觸發 | No |
下面的例子中展示了如何綁定事件到此組件:
~~~
<?php
use Phalcon\Acl\Adapter\Memory as AclList;
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
// ...
// 創建事件管理器
$eventsManager = new EventsManager();
// 綁定事件類型為acl
$eventsManager->attach(
"acl:beforeCheckAccess",
function (Event $event, $acl) {
echo $acl->getActiveRole();
echo $acl->getActiveResource();
echo $acl->getActiveAccess();
}
);
$acl = new AclList();
// Setup the $acl
// ...
// 綁定eventsManager到ACL組件
$acl->setEventsManager($eventsManager);
~~~
## 自定義適配器(Implementing your own adapters)
開發者要創建自己的擴展或已存在適配器則需要實現此[Phalcon\\Acl\\AdapterInterface](http://docs.iphalcon.cn/api/Phalcon_Acl_AdapterInterface.html)接口。
- 簡介
- 安裝
- 安裝(installlation)
- XAMPP下的安裝
- WAMP下安裝
- Nginx安裝說明
- Apache安裝說明
- Cherokee 安裝說明
- 使用 PHP 內置 web 服務器
- Phalcon 開發工具
- Linux 系統下使用 Phalcon 開發工具
- Mac OS X 系統下使用 Phalcon 開發工具
- Windows 系統下使用 Phalcon 開發工具
- 教程
- 教程 1:讓我們通過例子來學習
- 教程 2:INVO簡介
- 教程 3: 保護INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: V?kuró
- 教程 7:創建簡單的 REST API
- 組件
- 依賴注入與服務定位器
- MVC架構
- 使用控制器
- 使用模型
- 模型關系
- 事件與事件管理器
- Behaviors
- 模型元數據
- 事務管理
- 驗證數據完整性
- Workingwith Models
- Phalcon查詢語言
- 緩存對象關系映射
- 對象文檔映射 ODM
- 使用視圖
- 視圖助手
- 資源文件管理
- Volt 模版引擎
- MVC 應用
- 路由
- 調度控制器
- Micro Applications
- 使用命名空間
- 事件管理器
- Request Environmen
- 返回響應
- Cookie 管理
- 生成 URL 和 路徑
- 閃存消息
- 使用 Session 存儲數據
- 過濾與清理
- 上下文編碼
- 驗證Validation
- 表單_Forms
- 讀取配置
- 分頁 Pagination
- 使用緩存提高性能
- 安全
- 加密與解密 Encryption/Decryption
- 訪問控制列表
- 多語言支持
- 類加載器 Class Autoloader
- 日志記錄_Logging
- 注釋解析器 Annotations Parser
- 命令行應用 Command Line Applications
- Images
- 隊列 Queueing
- 數據庫抽象層
- 國際化
- 數據庫遷移
- 調試應用程序
- 單元測試
- 進階技巧與延伸閱讀
- 提高性能:下一步該做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl