Documentação do Symfony2
Renderizada do repositório symfony-docs-pt-BR no Github
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.
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.