Symfony2: Introduction to the Security Component part I
The Security Context
Central to the Security Component is the security context, which is an instance of SecurityContext. When all steps in the process of authenticating the user have been taken successfully, the security context may be asked if the authenticated user has access to a certain action or resource of the application.
use Symfony\Component\Security\SecurityContext;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
$context = new SecurityContext();
// authenticate the user...
if (!$context->isGranted('ROLE_ADMIN')) {
throw new AccessDeniedException();
}
A firewall for HTTP requests
Authenticating a user is done by the firewall. An application may have multiple secured areas, so the firewall is configured using a map of these secured areas. For each of these areas, the map contains a request matcher and a collection of listeners. The request matcher gives the firewall the ability to find out if the current request points to a secured area. The listeners are then asked if the current request can be used to authenticate the user.
Symfony2 Security: Using advanced Request matchers to activate firewalls
In the Symfony2 security documentation both the firewalls and the access control rules are demonstrated using the “path” option, which is used to determine if a firewall or rule is applicable to the current URL. Also the “ip” option is demonstrated. The fact of the matter is, the string based configuration options in security.yml
are transformed into objects of class RequestMatcher. This is a curious class in the HttpFoundation component which allows you to match a given Request object. The Security component uses it to determine if it should activate a certain firewall for the current request (usually only by checking the request’s path info).
Symfony Security Component & Silex: Adding a security voter for domain names
The Symfony Security Component has an AccessDecisionManager which decides whether or not the currently authenticated user has a right to be in some place (or for that matter, use a certain service from the service container, or even call a certain method). The decision manager looks at the current user’s roles, and compares them to the attributes that are required. It relies on dedicated voters to make it’s verdict.
The component itself ships with an AuthenticatedVoter. It supports the “IS_AUTHENTICATED_FULLY”, “IS_AUTHENTICATED_REMEMBERED” and “IS_AUTHENTICATED_ANONYMOUSLY” attributes, which allow you to differentiate between users who are authenticated in the normal way, via a “remember me” cookie, or anonymously (which means: no credentials were supplied, but the user still gets a security context).
Symfony2 Security: Creating dynamic roles (using RoleInterface)
The Symfony Security Component provides a two-layer security system: first it authenticates a user, then is authorizes him for the current request. Authentication means “identify yourself”. Authorization means: “let’s see if you have the right to be here”.
The deciding authority in this case will be the AccessDecisionManager. It has a number of voters (which you may create yourself too). Each voter will be asked if the authenticated user has the right “roles” for the current URL.
Silex: Using HttpFoundation and Doctrine DBAL in a Legacy PHP Application
In my previous post, I wrote about wrapping a legacy application in Silex, using output buffering and Twig. Finally, to allow for better decoupling as well as lazy loading of services, we passed the actual Silex\Application
instance as the first argument of legacy controllers.
The first and quite easy way we can enhance our legacy application, is to make use of the request
service (which contains all the details about the current request, wrapped inside the Symfony HttpFoundation’s Request
class). So, instead of reading directly from $_GET
and $_POST
, we can change the edit_category()
controller into the following:
Let Silex Wrap Your Legacy PHP Application (and add Twig for templating)
Ever since I am using the Symfony Framework (be it version 1 or 2), I tend to describe every other project I’ve done (including those that were built on top of some third party “framework” like Joomla or WordPress) as a “legacy project”. Though this has sometimes felt like treason, I still keep doing it: the quality of applications written using Symfony is usually so much higher in terms of maintainability, security and code cleanliness, that even a project done last year using “only PHP” looks like a mess and seems to be no good software at all. So I feel the strong urge to rebuild everything I have in portfolio (as do many other developers), but “this time, I will do it the right way”.
Symfony2: Testing Your Controllers
Apparently not everyone agrees on how to unit test their Symfony2 controllers. Some treat controller code as the application’s “glue”: a controller does the real job of transforming a request to a response. Thus it should be tested by making a request and check the received response for the right contents. Others treat controller code just like any other code - which means that every path the interpreter may take, should be tested.
Symfony2 Config Component: Config Definition and Processing
My previous post was about finding and loading configuration files. I now continue my Symfony2 Config Component quest with a post about the way you can “semantically expose your configuration” (using the TreeBuilder). I wrote this piece to later contribute it to the Symfony documentation so feedback is very welcome!
Validate configuration values
After loading configuration values from all kinds of resources, the values and their structure can be validated using the Definition
part of the Symfony2 Config Component. Configuration values are usually expected to show some kind of hierarchy. Also, values should be of a certain type, be restricted in number or be one of a given set of values. For example, the following configuration (in Yaml) shows a clear hierarchy and some validation rules that should be applied to it (like: “the value for ‘auto_connect’ must be a boolean”):
Symfony2 Config Component: Using FileLocator, Loaders and LoaderResolver
The Symfony2 Config Component provides several classes to help you find, load, combine, autofill and validate configuration values of any kind, whatever their source may be (Yaml, XML, INI files, or for instance a database).
Locating resources
Loading the configuration normally starts with a search for resources - in most cases: files. This can be done with FileLocator:
use Symfony\Component\Config\FileLocator;
$configDirectories = array(__DIR__ . DIRECTORY_SEPARATOR . 'app' . DIRECTORY_SEPARATOR . 'config');
$locator = new FileLocator($configDirectories);
$yamlUserFiles = $locator->locate('users.yml', null, false);
The locator receives a collection of locations where it should look for files. The first argument of locate()
is the name of the file to look for. The second argument may be the current path and when supplied, the locator will look in this directory first.
The third argument indicates whether or not the locator should return the first file it has found, or an array containing all matches.
Symfony2 & JMSSerializerBundle: Vendor MIME types and API versioning
The JMSSerializerBundle has a VersionExclusionStrategy
, which allows you to serialize/deserialize objects for a specific version of your API. You can mark the properties that are available for different versions using the @Since
and @Until
annotations:
use JMS\SerializerBundle\Annotation\Type;
use JMS\SerializerBundle\Annotation\Since;
use JMS\SerializerBundle\Annotation\Until;
class Comment
{
/**
* @Type("DateTime")
* @Since("1.2.0")
*/
private $createdAt;
/**
* @Type("DateTime")
* @Until("2.1.3")
*/
private $updatedAt;
}
The only thing you have to do is tell the serializer which version to use, before you start using it: