3

I am trying to write an event listener that needs access to the users permission level. In the controller I use the following code

Code:

$securityContext = $this->container->get('security.context');

if($securityContext->isGranted('ROLE_USER')){
    //Do Something
}

But outside of a controller I can't work out how to get the security context. Is it possible?

Theo Kouzelis
  • 3,195
  • 5
  • 37
  • 66
  • This might help: http://stackoverflow.com/questions/7561013/injecting-securitycontext-services-into-a-listener-class-in-symfony2-causes-circ – Thomas Kelley Apr 09 '13 at 16:50

3 Answers3

20

The best way to do this is using (as phpisuber said) dependency injection through the Service Container. But, instead of injecting the entire container (which is considered bad practice as it makes your entire class less testable and breaks loose coupling) you should inject the security.context service like so:

acme_foo.bar_service:
    class: %acme_foo.bar_service.class%
    arguments:
        - @security.context

Your service can be something like this:

<?php
namespace Acme\FooBundle\Service;

use Symfony\Component\Security\Core\SecurityContext;

class BarService
{
    /**
     * @var SecurityContext
     */
    protected $context;

    /**
     * @param SecurityContext $context
     */
    public function __construct($context)
    {
        $this->context = $context;
    }

    public function doSomething()
    {
        return $this->context->isGranted('ROLE_USER');
    }
}
Ramon Kleiss
  • 1,684
  • 15
  • 25
5

There is two ways to get it outside a controller:

Dependency Injection:

This is the correct way to do it, all you need is in the documentation here.

mybundle.model.mymodel:
class: %mybundle.model.myclass%
arguments: [@servicecontainer]

Quick and Dirty:

global $kernel;
$securityContext = $kernel->getContainer()->get('security.context');
phpisuber01
  • 7,585
  • 3
  • 22
  • 26
  • 3
    Please don't use the quick and dirty solution! You should never use a global! – Ramon Kleiss Apr 10 '13 at 09:44
  • This solution completely breaks the [Law of Demeter](http://en.wikipedia.org/wiki/Law_of_Demeter) – Touki Apr 10 '13 at 09:54
  • 2
    @Touki Care to explain more? Im genuinely interested. RamonKleiss is correct the Q&D solution is not a good idea to use, but I include it for those who want to make a quick concept check before spending the 20 minutes of facedesking through symfony configuration to inject the container into a model. Test your code, then go back and inject the container properly. Mmmhm. – phpisuber01 Apr 10 '13 at 12:14
  • 3
    @phpisuber01 This is the *Principle of Least Knowledge*. When you inject the whole service container as a dependency, your object lies on what it really needs. Your unit becomes hard to test without building the whole container. [This Video](http://www.youtube.com/watch?v=RlfLCWKxHJ0) may help you understand this principle – Touki Apr 10 '13 at 12:28
0

I know this post is a little dated, but it still came up as one of the first results on Google.

The answers in this post reference the SecurityContext class, which is no longer supported as of Symfony 2.6. The accepted answer for this post is misleading because of the class deprecation.

Try this code from this answer:

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use YourNameSpace\UserBundle\Entity\User;

class LoginController extends Controller{

    public function registerAction()
    {    
        $user = //Handle getting or creating the user entity likely with a posted form
        $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
        $this->get('security.token_storage')->setToken($token);
        $this->get('session')->set('_security_main', serialize($token));
    }
}
lsimonetti
  • 1,422
  • 3
  • 16
  • 26