Documentação do Symfony2
Renderizada do repositório symfony-docs-pt-BR no Github

Como proteger qualquer serviço ou método em sua aplicação

No capítulo de segurança, você pode ver como proteger um controlador solicitando o serviço security.context do Container de Serviço e verificando o papel (role) do usuário atual:

// ...
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

public function helloAction($name)
{
    if (false === $this->get('security.context')->isGranted('ROLE_ADMIN')) {
        throw new AccessDeniedException();
    }

    // ...
}

Você também pode proteger qualquer serviço de forma semelhante ao injetar o serviço security.context nele. Para uma introdução geral sobre como injetar dependências em serviços veja o capítulo do livro Container de Serviço. Por exemplo, supondo que você tenha uma classe NewsletterManager que envia e-mails e você quer restringir o seu uso apenas aos usuários que possuam o papel ROLE_NEWSLETTER_ADMIN. Antes de adicionar a segurança, a classe parece com o seguinte:

// src/Acme/HelloBundle/Newsletter/NewsletterManager.php
namespace Acme\HelloBundle\Newsletter;

class NewsletterManager
{

    public function sendNewsletter()
    {
        // ... where you actually do the work
    }

    // ...
}

Seu objetivo é verificar o papel do usuário quando o método sendNewsletter() é chamado. O primeiro passo para isso é injetar o serviço security.context no objeto. Uma vez que não fará sentido não realizar a verificação de segurança, esse é um candidato ideal para injeção de construtor, que garante que o objeto do contexto de segurança (security context) estará disponível dentro da classe NewsletterManager:

namespace Acme\HelloBundle\Newsletter;

use Symfony\Component\Security\Core\SecurityContextInterface;

class NewsletterManager
{
    protected $securityContext;

    public function __construct(SecurityContextInterface $securityContext)
    {
        $this->securityContext = $securityContext;
    }

    // ...
}

Então, em sua configuração de serviço, você pode injetar o serviço:

O serviço injetado pode agora ser utilizado para realizar a verificação de segurança quando o método sendNewsletter() é chamado:

namespace Acme\HelloBundle\Newsletter;

use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Core\SecurityContextInterface;
// ...

class NewsletterManager
{
    protected $securityContext;

    public function __construct(SecurityContextInterface $securityContext)
    {
        $this->securityContext = $securityContext;
    }

    public function sendNewsletter()
    {
        if (false === $this->securityContext->isGranted('ROLE_NEWSLETTER_ADMIN')) {
            throw new AccessDeniedException();
        }

        // ...
    }

    // ...
}

Se o usuário atual não possui o ROLE_NEWSLETTER_ADMIN, ele será solicitado a efetuar o login.

Protegendo Métodos usando Anotações

Você também pode proteger chamadas de métodos em qualquer serviço com anotações usando o bundle opcional JMSSecurityExtraBundle. Esse bundle está incluído na Distribuição Standard do Symfony.

Para habilitar a funcionalidade de anotações, tag o serviço que você deseja proteger com a tag security.secure_service (você também pode ativar automaticamente essa funcionalidade para todos os serviços, consulte a sidebar abaixo):

Você pode então alcançar os mesmos resultados descritos acima utilizando uma anotação:

namespace Acme\HelloBundle\Newsletter;

use JMS\SecurityExtraBundle\Annotation\Secure;
// ...

class NewsletterManager
{

    /**
     * @Secure(roles="ROLE_NEWSLETTER_ADMIN")
     */
    public function sendNewsletter()
    {
        // ...
    }

    // ...
}

Note

As anotações funcionam porque uma classe proxy é criada para a sua classe que executa as verificações de segurança. Isso significa que, enquanto você pode usar anotações em métodos públicos e protegidos, você não pode usá-las em métodos privados ou em métodos marcados como final.

O JMSSecurityExtraBundle também permite que você proteja os parâmetros e valores de retorno dos métodos. Para mais informações, consulte a documentação JMSSecurityExtraBundle.