I will skip the infamous hello world post and instead introduce a new cool, and powerful feature for the Symfony2 Security component. You might even go as far as calling this a killer feature as it makes authorization control not only a lot faster, but also infinitely simpler!
If you have used the Symfony2 Security Component to any modest degree, you will know that we have a quite heavy voting system which uses attributes like IS_AUTHENTICATED_FULLY to make authorization decisions. Now that system works quite well unless you need to make a bit more complex access checks. Let’s say you want to check whether the user has either role “A”, or role “B” and “C”. What you can do in this case is either write out these checks in your code
<?php
$context->isGranted('A') || ($context->isGranted('B') && $context->isGranted('C'))
or alternatively, you write your own security voter with a special attribute. If you know the internals a bit, then you know that a call to isGranted() is not the most lightweight thing you can do. We first need to possibly re-authenticate your token, and then collect votes from all the registered voters to finally be able to make the decision whether to grant access or not. So if you are concerned about performance, then you should not be all too generous with the isGranted() calls. The second option would work as well, but writing a new voter each time you need to make a new check does not really seem ideal either. Fortunately, we can do better.
In this post, I want to introduce a new expression-based authorization language. It’s quite a long term, but what’s behind it is rather simple. If we come back to the example above, we can now use an expression to perform the checks:
<?php
use JMS\SecurityExtraBundle\Security\Authorization\Expression\Expression;
$context->isGranted(new Expression('hasRole("A") or (hasRole("B") and hasRole("C"))'));
Doing this has the advantage that we only need to make a single call to isGranted(). Besides, expressions are compiled to optimized PHP code which gives us another nice speed boost.
Having a dedicated authorization language, opens up some new possibilities for more complex checks:
<?php
use JMS\SecurityExtraBundle\Annotation\PreAuthorize;
class MyController
{
/**
* @PreAuthorize("hasRole('ADMIN') or #toDelete.getId() == user.getId()")
*/
public function indexAction(User $toDelete)
{
// ...
}
}
In this example, we check whether the current user is either an admin, or the user that should be deleted himself.
There are a lot more expressions that you can build which I cannot all put into a single blog post, but which you can find in the the documentation.
Enjoy!
that is a really killer feature!
thanks for sharing!
Killer feature indeed!