The ability to execute an action can be restricted to users with certain privileges. The tools provided by symfony for this purpose allow the creation of secure applications, where users need to be authenticated before accessing some features or parts of the application. Securing an application requires two steps: declaring the security requirements for each action and logging in users with privileges so that they can access these secure actions.
6.5.1. Access Restriction
Before being executed, every action passes by a special filter that checks if the current user has the privileges to access the requested action. In symfony, privileges are composed of two parts:
- Secure actions require users to be authenticated.
- Credentials are named security privileges that allow organizing security by group.
Restricting access to an action is simply made by creating and editing a YAML configuration file called security.yml
in the module config/
directory. In this file, you can specify the security requirements that users must fulfill for each action or for all
actions. Listing 6-21 shows a sample security.yml
.
Listing 6-21 - Setting Access Restrictions, in apps/frontend/modules/mymodule/config/security.yml
read:
is_secure: off # All users can request the read action
update:
is_secure: on # The update action is only for authenticated users
delete:
is_secure: on # Only for authenticated users
credentials: admin # With the admin credential
all:
is_secure: off # off is the default value anyway
Actions are not secure by default, so when there is no security.yml
or no mention of an action in it, actions are accessible by everyone. If there is a security.yml
, symfony looks for the name of the requested action and, if it exists, checks the fulfillment of the security requirements. What happens when a user tries to access a restricted action depends on his credentials:
- If the user is authenticated and has the proper credentials, the action is executed.
- If the user is not identified, he will be redirected to the default login action.
- If the user is identified but doesn't have the proper credentials, he will be redirected to the default secure action, shown in Figure 6-1.
The default login and secure pages are pretty simple, and you will probably want to customize them. You can configure which actions are to be called in case of insufficient privileges in the application settings.yml
by changing the value of the properties shown in Listing 6-22.
![The default secure action page](/static/libros/imagenes/symfony-1-1-en/F0601.jpg)
Figure 6.1 The default secure action page
Listing 6-22 - Default Security Actions Are Defined in apps/frontend/config/settings.yml
all:
.actions:
login_module: default
login_action: login
secure_module: default
secure_action: secure
6.5.2. Granting Access
To get access to restricted actions, users need to be authenticated and/or to have certain credentials. You can extend a user's privileges by calling methods of the sfUser
object. The authenticated status of the user is set by the setAuthenticated()
method and can be checked with isAuthenticated()
. Listing 6-23 shows a simple example of user authentication.
Listing 6-23 - Setting the Authenticated Status of a User
class myAccountActions extends sfActions
{
public function executeLogin($request)
{
if ($request->getParameter('login') == 'foobar')
{
$this->getUser()->setAuthenticated(true);
}
}
public function executeLogout()
{
$this->getUser()->setAuthenticated(false);
}
}
Credentials are a bit more complex to deal with, since you can check, add, remove, and clear credentials. Listing 6-24 describes the credential methods of the sfUser
class.
Listing 6-24 - Dealing with User Credentials in an Action
class myAccountActions extends sfActions
{
public function executeDoThingsWithCredentials()
{
$user = $this->getUser();
// Add one or more credentials
$user->addCredential('foo');
$user->addCredentials('foo', 'bar');
// Check if the user has a credential
echo $user->hasCredential('foo'); => true
// Check if the user has both credentials
echo $user->hasCredential(array('foo', 'bar')); => true
// Check if the user has one of the credentials
echo $user->hasCredential(array('foo', 'bar'), false); => true
// Remove a credential
$user->removeCredential('foo');
echo $user->hasCredential('foo'); => false
// Remove all credentials (useful in the logout process)
$user->clearCredentials();
echo $user->hasCredential('bar'); => false
}
}
If a user has the foo
credential, that user will be able to access the actions for which the security.yml
requires that credential. Credentials can also be used to display only authorized content in a template, as shown in Listing 6-25.
Listing 6-25 - Dealing with User Credentials in a Template
<ul>
<li><?php echo link_to('section1', 'content/section1') ?></li>
<li><?php echo link_to('section2', 'content/section2') ?></li>
<?php if ($sf_user->hasCredential('section3')): ?>
<li><?php echo link_to('section3', 'content/section3') ?></li>
<?php endif; ?>
</ul>
As for the authenticated status, credentials are often given to users during the login process. This is why the sfUser
object is often extended to add login and logout methods, in order to set the security status of users in a central place.
Tip Among the symfony plug-ins, the sfGuardPlugin
(http://trac.symfony-project.org/wiki/sfGuardPlugin) extends the session class to make login and logout easy. Refer to Chapter 17 for more information.
6.5.3. Complex Credentials
The YAML syntax used in the security.yml file allows you to restrict access to users having a combination of credentials, using either AND-type or OR-type associations. With such a combination, you can build a complex workflow and user privilege management system — for instance, a content management system (CMS) back-office accessible only to users with the admin credential, where articles can be edited only by users with the editor
credential and published only by the ones with the publisher
credential. Listing 6-26 shows this example.
Listing 6-26 - Credentials Combination Syntax
editArticle:
credentials: [ admin, editor ] # admin AND editor
publishArticle:
credentials: [ admin, publisher ] # admin AND publisher
userManagement:
credentials: [[ admin, superuser ]] # admin OR superuser
Each time you add a new level of square brackets, the logic swaps between AND and OR. So you can create very complex credential combinations, such as this:
credentials: [[root, [supplier, [owner, quasiowner]], accounts]]
# root OR (supplier AND (owner OR quasiowner)) OR accounts