How to Use advanced ACL Concepts
How to Use advanced ACL Concepts¶
The aim of this article is to give a more in-depth view of the ACL system, and also explain some of the design decisions behind it.
Symfony’s object instance security capabilities are based on the concept of an Access Control List. Every domain object instance has its own ACL. The ACL instance holds a detailed list of Access Control Entries (ACEs) which are used to make access decisions. Symfony’s ACL system focuses on two main objectives:
- providing a way to efficiently retrieve a large amount of ACLs/ACEs for your domain objects, and to modify them;
- providing a way to easily make decisions of whether a person is allowed to perform an action on a domain object or not.
As indicated by the first point, one of the main capabilities of Symfony’s ACL system is a high-performance way of retrieving ACLs/ACEs. This is extremely important since each ACL might have several ACEs, and inherit from another ACL in a tree-like fashion. Therefore, no ORM is leveraged, instead the default implementation interacts with your connection directly using Doctrine’s DBAL.
The ACL system is completely decoupled from your domain objects. They don’t even have to be stored in the same database, or on the same server. In order to achieve this decoupling, in the ACL system your objects are represented through object identity objects. Every time you want to retrieve the ACL for a domain object, the ACL system will first create an object identity from your domain object, and then pass this object identity to the ACL provider for further processing.
This is analog to the object identity, but represents a user, or a role in your application. Each role, or user has its own security identity.
For users, the security identity is based on the username. This means that,
if for any reason, a user’s username was to change, you must ensure its
security identity is updated too. The
method is there to handle the update.
Database Table Structure¶
The default implementation uses five database tables as listed below. The tables are ordered from least rows to most rows in a typical application:
- acl_security_identities: This table records all security identities (SID)
which hold ACEs. The default implementation ships with two security
- acl_classes: This table maps class names to a unique ID which can be referenced from other tables.
- acl_object_identities: Each row in this table represents a single domain object instance.
- acl_object_identity_ancestors: This table allows all the ancestors of an ACL to be determined in a very efficient way.
- acl_entries: This table contains all ACEs. This is typically the table with the most rows. It can contain tens of millions without significantly impacting performance.
Scope of Access Control Entries¶
Access control entries can have different scopes in which they apply. In Symfony, there are basically two different scopes:
- Class-Scope: These entries apply to all objects with the same class.
- Object-Scope: This was the scope solely used in the previous article, and it only applies to one specific object.
Sometimes, you will find the need to apply an ACE only to a specific field of the object. Suppose you want the ID only to be viewable by an administrator, but not by your customer service. To solve this common problem, two more sub-scopes have been added:
- Class-Field-Scope: These entries apply to all objects with the same class, but only to a specific field of the objects.
- Object-Field-Scope: These entries apply to a specific object, and only to a specific field of that object.
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.