Este foro ya no está activo, así que no puedes publicar nuevas preguntas ni responder a las preguntas existentes.

Security Voters Symfony2

15 de diciembre de 2013

Creo haber seguido todos los pasos para implementar un security voter con el fin de que los usuarios que hayan creado un objeto sean los únicos que puedan modificarlo.

1) app/config/services.yml

wars.profesorbundle.security.ownervoter:
    class: Wars\ProfesorBundle\Security\OwnerVoter

2) Implementación de OwnerVoter.php

<?php
 
namespace Wars\ProfesorBundle\Security;
 
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
 
class OwnerVoter implements VoterInterface
{
    public function supportsAttribute($attribute)
    {
        return 'ROLE_EDITAR_MENSAJE' == $attribute;
    }
 
    public function supportsClass($class)
    {
        return true;
    }
 
    public function vote(TokenInterface $token, $object, array $attributes)
    {
        $vote = VoterInterface::ACCESS_ABSTAIN;
 
        foreach ($attributes as $attribute) {
 
            if (false === $this->supportsAttribute($attribute)) {
                continue;
            }
 
            $user = $token->getUser();
            $vote = VoterInterface::ACCESS_DENIED;
 
            // comprobar que el mensaje que se edita fue publicado
            // por este mismo profesor
            if ($object->getProfesor()->getId() === $user->getId()) {
                $vote = VoterInterface::ACCESS_GRANTED;
            }
        }
 
        return $vote;
    }
}

Y no se donde está el error pero no permite que el usuario creador de un objeto pueda editarlo porque siempre me devuelve false al hacer la comprobación (y eso que me aseguro de que el creador del objeto y el usuario que pretende modificarlo son iguales):

if (false === $this->get('security.context')->isGranted('ROLE_EDITAR_MENSAJE', $panel))

De todas formas, mi duda es que no se si es realmente necesario crear un Security Voter si simplemente en el Controller puedo comprobar si el usuario conectado es creador del objeto que pide modificar realizando una simple comparación:

$panel->getUsuario()->getId() == this->get('security.context')->getToken()->getUser()

Respuestas

#1

Me lo soluciono yo mismo, como siempre pequeñas cosas que retrasan el trabajo:

Importar a app/config/config.yml los ficheros como app/config/services.yml

@Jorge_Gante

17 diciembre 2013, 4:06
#2

Respecto a la duda que tienes sobre si sería lo mismo un security voter que hacer la comprobación en el controlador, puede parecer que sí, pero en la práctica son muy diferentes.

Si haces una comprobación en un controlador, ese código deja de ser reutilizable en otras partes de la aplicación. Además, la comprobación es totalmente ajena al sistema de seguridad de Symfony.

Sin emabrgo, si usas un security voter, vas a poder reutilizar esa lógica que decide si un usuario puede hacer una determinada acción. Además, los voters se combinan unos con otros y así puedes llegar a hacer combinaciones muy interesantes. Ejemplo: que los usuarios puedan editar sus propios objetos, pero sólo si acceden desde la intranet de la empresa. En ese caso usarías el voter que has hecho y un voter que compruebe la IP del usuario.

Después, sólo tienes que configurar que la decisión sobre si un usuario puede editar un objeto sea por unanimidad de todos los voters activos. En la sección Changing the Access Decision Strategy de la documentación oficial de Symfony2 se explica mejor.

@javiereguiluz

17 diciembre 2013, 22:22