Curso Symfony 2: Seguridad de acceso
Uno de los aspectos más importantes en el desarrollo de cualquier aplicación es la Seguridad de acceso, para ello Symfony 2 dispone de una moderna librería que se encarga de las validaciones de acceso y seguridad.
En este capítulo nos dispondremos a crear un ejemplo básico de seguridad que nos permita hacer el “login” de los usuarios y a su vez bloquear el acceso a determinados usuarios según su rol, para ello tendremos que adentrarnos en como funciona la librería de seguridad de Symfony2, luego crearemos las estructuras necesarias para definir un mini-backend donde crearemos unos CRUD’s para usuarios y roles utilizando Doctrine como proveedor de usuarios.
Autenticación vs. Autorización
Representan los 2 conceptos más fundamentales de seguridad en Symfony, el primero se encarga de verificar si el usuario en cuestión está Autenticado (logeado) y se le conoce como “Firewall”, el segundo verifica si el usuario tiene los permisos o “roles” necesarios y se le conoce como “access_control”.
El primer paso es verificar si el usuario está o no autenticado, en tal caso lo deja pasar y el segundo paso es verificar si el usuario tiene el rol necesario para dicha acción, para comprenderlo mejor veamos un ejemplo básico del archivo de configuración:
# proyecto/app/config/security.yml security: firewalls: secured_area: pattern: ^/ anonymous: ~ http_basic: realm: "Secured Demo Area" access_control: - { path: ^/admin, roles: ROLE_ADMIN } providers: in_memory: users: usuario: { password: user, roles: 'ROLE_USER' } admin: { password: kitten, roles: 'ROLE_ADMIN' } encoders: Symfony\Component\Security\Core\User\User: plaintext
Vemos como primer elemento definido los conjuntos de firewall y en él una “secured_area” donde:
- pattern: es una expresión regular para hacer empatar la URL, toda ruta que empate con ello obligará al mecanismo de firewall que verifique si el usuario está autenticado, si no lo está procederá a re-dirigirlo al formulario de autenticación (en el caso anteterior mostrar el díalogo nativo de autenticación HTTP del navegador).
- anonymous: ~: indica que permite usuarios anónimos, no se debe aplicar en caso de backends.
- http_basic: indica que utilice la autenticación HTTP.
Por su parte el Mecanismo de Autorización “access_control” actúa de forma diferente, porque aunque dependa de que el usuario esté autenticado verifica si el mismo dispone de los permisos (roles) necesarios para determinada operación:
- – { path: ^/admin, roles: ROLE_ADMIN }indica una regla básica para autorización, donde en toda ruta que coincida al principio con /admin, el usuario debe de tener dicho rol “ROLE_ADMIN” indicado.
[tipexperto titulo = “Nota”] Puedes añadir tantos access_control como necesites.[/tipexperto]
“providers” simplemente define el proveedor de usuario, que en este caso es en memoria, y “encoders” define el codificador de la contraseña, el cual debe ser de algún tipo de HASH como SHA512, en el ejemplo se usa texto plano. (más adelante se exponen ejemplos detallados).
Configuraciones del Control de Acceso
El control de acceso no sólo se limita a controlar que el usuario cumpla con un rol determinado para un patrón de ruta determinada, permite cierta flexibilidad con el que podrás adaptarte a las necesidades de seguridad de tu aplicación.
Protegiendo por IP
Tan simple como añadir el parámetro ip, con la misma puedes obligar a que una ruta solo se pueda acceder desde dicha ip (ideal para el backend interno):
# app/config/security.yml security: # ... access_control: - { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
Protegiendo por Canal
Si dispones de un certificado SSL puedes obligar a que la ruta solo esté disponible desde https, especificando requires_channel:
# app/config/security.yml security: # ... access_control: - { path: ^/cart/checkout, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https}
Protegiendo un Controlador
En ocasiones necesitamos que el controlador se encargue del control de acceso, de forma que podamos flexibilizarlo según nuestro modelo de negocios, para ello podremos acceder al contexto de seguridad desde nuestros controladores:
//dentro de un controlador use Symfony\Component\Security\Core\Exception\AccessDeniedException; // ... public function helloAction($name) { if (false === $this->get(’security.context’)->isGranted(’ROLE_ADMIN’)) { throw new AccessDeniedException(); } // ... }
También puede optar por instalar y utilizar el Bundle opcional JMSSecurityExtraBundle, el cual puede asegurar su controlador usando anotaciones:
//dentro de un controlador use JMS\SecurityExtraBundle\Annotation\Secure; /** * @Secure(roles="ROLE_ADMIN") */ public function helloAction($name) { // ... }
Para más información, consulte la documentación de JMSSecurityExtraBundle. Si estás usando la distribución estándar de Symfony, este paquete está disponible de forma predeterminada. Si no es así, lo puedes descargar e instalar.
Controlando el acceso desde plantilla
Incluso puedes verificar si el usuario tiene acceso desde la misma plantilla, útil para ocultar segmentos a roles específicos:
Desde Twig
{% if is_granted(’ROLE_ADMIN’) %} <a href="...">Delete</a> {% endif %}
Desde PHP
<?php if ($view[’security’]->isGranted(’ROLE_ADMIN’)): ?> <a href="...">Delete</a> <?php endif; ?>
Recuperando del objeto usuario
Desde un controlador, puedes acceder fácilmente a la instancia del usuario actual utilizando el Mecanismo de inyección de dependencias:
//dentro de un controlador public function indexAction() { $user = $this->get(’security.context’)->getToken()->getUser(); }
Tutorial: mini-backend de usuarios con Doctrine
Realmente el ejemplo anterior es demasiado básico como para llevarlo a una aplicación real, y una de las opciones más tentadoras es utilizar Doctrine como proveedor de los Usuarios, con el cual podamos crear Roles y Usuarios desde CRUD’s elaborados por el mismo framework y crear nuestro propio esquema de seguridad, debo resaltar que existen muchos Bundles prefabricados como el FOSUserBundle que facilitan enormemente ésta tarea, pero si quieres profundizar puedes seguir el siguiente tutorial para conocer a fondo como se hace desde 0 con Doctrine ;-).
Paso 1: Crea las entidades básicas
Antes de empezar debemos de definir las entidades básicas para ser utilizadas como proveedor de usuarios y roles en Sf2, dichas entidades User y Role deben de implementar las interfaces Symfony\Component\Security\Core\User\UserInterface y Symfony\Component\Security\Core\Role\RoleInterface respectivamente, así que añade estas 2 entidades a tu directorio “proyecto/src/MDW/BlogBundle/Entity”:
User.php:
<?php // proyecto/src/MDW/BlogBundle/Entity/User.php namespace MDW\BlogBundle\Entity; use Symfony\Component\Security\Core\User\UserInterface; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="admin_user") */ class User implements UserInterface { /** * @var integer $id * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @ORM\Column(type="string", length="255") */ protected $username; /** * @ORM\Column(name="password", type="string", length="255") */ protected $password; /** * @ORM\Column(name="salt", type="string", length="255") */ protected $salt; /** * se utilizó user_roles para no hacer conflicto al aplicar ->toArray en getRoles() * @ORM\ManyToMany(targetEntity="Role") * @ORM\JoinTable(name="user_role", * joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")}, * inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")} * ) */ protected $user_roles; public function __construct() { $this->user_roles = new \Doctrine\Common\Collections\ArrayCollection(); } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set username * * @param string $username */ public function setUsername($username) { $this->username = $username; } /** * Get username * * @return string */ public function getUsername() { return $this->username; } /** * Set password * * @param string $password */ public function setPassword($password) { $this->password = $password; } /** * Get password * * @return string */ public function getPassword() { return $this->password; } /** * Set salt * * @param string $salt */ public function setSalt($salt) { $this->salt = $salt; } /** * Get salt * * @return string */ public function getSalt() { return $this->salt; } /** * Add user_roles * * @param Maycol\BlogBundle\Entity\Role $userRoles */ public function addRole(\Maycol\BlogBundle\Entity\Role $userRoles) { $this->user_roles[] = $userRoles; } public function setUserRoles($roles) { $this->user_roles = $roles; } /** * Get user_roles * * @return Doctrine\Common\Collections\Collection */ public function getUserRoles() { return $this->user_roles; } /** * Get roles * * @return Doctrine\Common\Collections\Collection */ public function getRoles() { return $this->user_roles->toArray(); //IMPORTANTE: el mecanismo de seguridad de Sf2 requiere ésto como un array } /** * Compares this user to another to determine if they are the same. * * @param UserInterface $user The user * @return boolean True if equal, false othwerwise. */ public function equals(UserInterface $user) { return md5($this->getUsername()) == md5($user->getUsername()); } /** * Erases the user credentials. */ public function eraseCredentials() { } }
Role.php:
<?php // proyecto/src/MDW/BlogBundle/Entity/Role.php namespace MDW\BlogBundle\Entity; use Symfony\Component\Security\Core\Role\RoleInterface; use Doctrine\ORM\Mapping as ORM; /** * @ORM\Entity * @ORM\Table(name="admin_roles") */ class Role implements RoleInterface { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id; /** * @ORM\Column(name="nombre", type="string", length="255") */ protected $name; /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set name * * @param string $name */ public function setName($name) { $this->name = $name; } /** * Get name * * @return string */ public function getName() { return $this->name; } public function getRole() { return $this->getName(); } public function __toString() { return $this->getRole(); } }
Una vez creadas nuestras entidades, accedemos a la consola de Symfony2 y generamos las tablas en Base de Datos:
$ app/console doctrine:schema:update --force
Paso 2: Generando los CRUD’s
Una vez creadas las entidades en DB, procedemos a crear los CRUD’s desde la consola de symfony:
$ app/console doctrine:generate:crud
Seguimos los pasos colocando MDWBlogBundle:Role, luego nos solicita si deseamos crear las opciones de escritura, le decimos “y” (sí), formato del CRUD: annotation, y finalmente en el Routes prefix colocamos /admin/role, este paso es importante porque a la ruta le asignamos el prefijo /admin para que nos permita empatar luego con el access_control, confirmamos y aparecerá el mensaje “You can now start using the generated code!”
Procedemos a aplicar lo mismo pero en este caso con MDWBlogBundle:User y en Routes prefix colocamos /admin/user
Ahora añadiremos las rutas a nuestro archivo de rutas (proyecto/src/MDW/BlogBundle/Resources/Config/routing.yml), porque al crearlas como Anotaciones las mismas no se añaden automáticamente:
#proyecto/src/MDW/BlogBundle/Resources/Config/routing.yml # final del archivo: MDWAnnotations: resource: "@MDWBlogBundle/Controller/" prefix: / type: annotation
De ésta forma añadiremos todas las rutas definidas por anotaciones del directorio Controller, ésta técnica forma parte del SensioFrameworkExtraBundle y nos permite definir las rutas directamente en nuestros controladores. si utilizas la Versión estándar de Symfony2 este Bundle viene por defecto.
Ya con esto podemos acceder a nuestros crud’s desde localhost/proyecto/web/app_dev.php/admin/user, pero aún debemos modificar ciertos aspectos en el controlador User para codificar el hash de contraseña.
Primero añadiremos la siguiente función en el controlador de usuarios:
// proyecto/src/MDW/BlogBundle/Controller/UserController.php // añadimos esta función private function setSecurePassword(&$entity) { $entity->setSalt(md5(time())); $encoder = new \Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder('sha512', true, 10); $password = $encoder->encodePassword($entity->getPassword(), $entity->getSalt()); $entity->setPassword($password); }
Luego modificamos las funciones de las acciones correspondientes a create y update, añadiendo la llamada al la función anterior para establecer el hash de la contraseña con el algoritmo SHA512:
// proyecto/src/MDW/BlogBundle/Controller/UserController.php //funcion createAction: public function createAction() { $entity = new User(); $request = $this->getRequest(); $form = $this->createForm(new UserType(), $entity); $form->bindRequest($request); if ($form->isValid()) { //establecemos la contraseña: -------------------------- $this->setSecurePassword($entity); $em = $this->getDoctrine()->getEntityManager(); $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl('admin_user_show', array('id' => $entity->getId()))); } return array( 'entity' => $entity, 'form' => $form->createView() ); } //... //funcion updateAction: public function updateAction($id) { $em = $this->getDoctrine()->getEntityManager(); $entity = $em->getRepository('MDWBlogBundle:User')->find($id); if (!$entity) { throw $this->createNotFoundException('Unable to find User entity.'); } $editForm = $this->createForm(new UserType(), $entity); $deleteForm = $this->createDeleteForm($id); $request = $this->getRequest(); //obtiene la contraseña actual ----------------------- $current_pass = $entity->getPassword(); $editForm->bindRequest($request); if ($editForm->isValid()) { //evalua si la contraseña fue modificada: ------------------------ if ($current_pass != $entity->getPassword()) { $this->setSecurePassword($entity); } $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl('admin_user_edit', array('id' => $id))); } return array( 'entity' => $entity, 'edit_form' => $editForm->createView(), 'delete_form' => $deleteForm->createView(), ); }
Por último sólo nos queda eliminar del formulario (src/MDW/BlogBundle/Form/UserType.php) el campo salt el cual no debe ser modificado por el usuario:
<?php // proyecto/src/MDW/BlogBundle/Form/UserType.php namespace MDW\BlogBundle\Form; use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; class UserType extends AbstractType { public function buildForm(FormBuilder $builder, array $options) { $builder ->add('username') ->add('password') //->add('salt') //No necesitamos que salt sea mostrado --------------- ->add('user_roles') ; } public function getName() { return 'mdw_blogbundle_usertype'; } }
Ahora puedes proceder a registrar usuarios y roles, es muy importante que al menos crees los roles “ROLE_ADMIN” y “ROLE_USER” y dos usuarios (uno con un rol diferente) antes de que procedas en aplicar el esquema de seguridad, de lo contrario no tendrás usuario con que loguearte ;-).
Paso 3: Creando el esquema de seguridad
Ahora procedemos a sobreescribir nuestro esquema de seguridad (proyecto/app/config/security.yml), recomiendo que antes de hacerlo guardes una copia del security.yml.
# proyecto/app/config/security.yml security: encoders: MDW\BlogBundle\Entity\User: algorithm: sha512 encode-as-base64: true iterations: 10 providers: user_db: entity: { class: MDW\BlogBundle\Entity\User, property: username } firewalls: dev: pattern: ^/(_(profiler|wdt)|css|images|js)/ security: false login: pattern: ^/admin/login$ security: false secured_area: pattern: ^/admin/ # http_basic: # realm: "Introduzca Usuario y Contraseña" form_login: login_path: /admin/login check_path: /admin/login_check logout: path: /admin/logout target: / access_control: - { path: ^/admin, roles: ROLE_ADMIN }
Como puedes apreciar en “encoders” se ha definido un codificador especifico para la entidad User, utilizando el algoritmo SHA512, además codificandolo en Base64 con 10 iteracciones, tal cual se apreció en la función setSecurePassword del controlador.
En “providers” se estableció nuestra entidad User de Doctrine, especificando el campo correspondiente al username, es cual es el mismo username en nuestra entidad.
En “firewalls” se ha añadido la nueva regla (o firewall) login desde la cual se aplica el parametro security: false lo que permite acceder a la misma sin autenticarse, de lo contrario el formulario de login nunca lo podremos visializar.
Además en “secured_area” se ha eliminado anonymous, se ha establecido “form_login” donde definimos la ruta para el login del sistema, y se definió una ruta personalizada para el “log_out“, donde en “target” podemos definir el path hacia donde redirigir cuando los usuarios cierren sesión.
Para culminar sólo necesitamos crear el controlador y vista para nuestro login, por lo que debes de crear el archivo SecurityController.php en el directorio (proyecto/src/MDW/BlogBundle/Controller):
SecurityController.php
<?php // proyecto/src/MDW/BlogBundle/Controller/SecurityController.php namespace MDW\BlogBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Symfony\Component\Security\Core\SecurityContext; /** * Security controller. * * @Route("/admin") */ class SecurityController extends Controller { /** * Definimos las rutas para el login: * @Route("/login", name="login") * @Route("/login_check", name="login_check") */ public function loginAction() { $request = $this->getRequest(); $session = $request->getSession(); // obtiene el error de inicio de sesión si lo hay if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) { $error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR); } else { $error = $session->get(SecurityContext::AUTHENTICATION_ERROR); } return $this->render('MDWBlogBundle:Security:login.html.twig', array( // el último nombre de usuario ingresado por el usuario 'last_username' => $session->get(SecurityContext::LAST_USERNAME), 'error' => $error, )); } } ?>
Ahora crea el directorio “Security” dentro de (proyecto/src/MDW/BlogBundle/Resources/views) y procede a crear el archivo de vista:
login.html.twig
{# proyecto/src/MDW/BlogBundle/Resources/views/Security/login.html.twig #} {% if error %} <div>{{ error.message }}</div> {% endif %} <form action="{{ path('login_check') }}" method="post"><label for="username">Username:</label> <input id="username" type="text" name="_username" value="{{ last_username }}" /> <label for="password">Password:</label> <input id="password" type="password" name="_password" /> <input type="submit" name="login" /> </form>
Y con ello ya puedes intentar acceder a localhost/proyecto/web/admin/user y probar el sistema de seguridad de Symfony2 (vaciar la caché en el caso de entrar al entorno de producción), si creaste previamente 2 usuarios, intenta acceder con el usuario que no tiene el rol “ROLE_ADMIN” y verás como te niega el acceso, en cambio si pruebas con un usuario con dicho rol, puedes entrar perfectamente.
Resumen Final
En esta ocasión apreciamos el complejo sistema de seguridad de Symfony2, en donde un firewall verifica si el usuario está o no logueado, y un access control vigila que dicho usuario no pueda acceder a contenido del cual no se le ha dado acceso, también conocimos que se pueden definir providers diferentes para contener a nuestros usuarios y encoders para personalizar el HASH de la contraseña.
Además interactuamos con dicho sistema a través de un “rápido” tutorial que nos permitió resolver las inquietudes más directas en cuanto a creación de un básico RBAC (Role-based Access Control), reitero que no es la única forma de hacerlo y que existen muchos Bundles Prefabricados como el FOSUserBundle que nos facilita enormemente ésta tarea, pero si no se conoce debidamente la base puede resultar una verdadera caja negra el usar un Bundle sin el previo conocimiento de como Symfony2 implementa tales mecanismos.
[…] 0.0/5 (0 votes cast)Hemos llegado al último capítulo de esta Guía de symfony2 con la entrega del capítulo 13 publicado hoy sobre como aplicación la seguridad en el acceso a nuestras […]
[…] Capítulo 13 – Seguridad de Acceso – Maycol Alvarez […]
Excelente articulo, muy bien explicado.
Excelente artículo, tengo una pequeña duda:
Paso 1: Crea las entidades básicas: dichas entidades User y Role
¿Deben tener ese mismo nombre la entidad? yo tengo en un symfony de prueba Usuarios y ahí implemento el userinterface y no tengo una entidad Role, lo tengo como un campo de la tabla Usuarios de tipo string, ¿ esto es correcto ?, ¿debería separarlo?.
Gracias por el curso y por la calidad del mismo, un saludo!
Puedes cambiar el nombre, solo que debes de asegurarte de que ésa entidad sea la que uses en toda la aplicación (obvio :-D).
La entidad Role no es necesaria, si te fijas en la función getRoles() de la Entidad User se espera devolver un Array de los Roles que el usuario tenga, por lo tanto allí puedes generar o un array estático con los roles que quieras, o como desees implementarlo, la ventaja de usar la entidad Role es dar semántica y aprovechar el mecanismo de asociaciones de Doctrine 😉
Muchas gracias Maycol 😀
Genial curso!!!, para cuando el PDF???
Muy bien explicado!! Tengo una duda interesante, y no se como solucionarla, a ver si me podeis ayudar!
Resulta que necesito tener dos logins en la pagina, uno sera para el area de clientes que consiste unicamente en permitirle el acceso a una seccion donde tendra un fichero descargable propio para el, es decir, tendria ROLE_USER, y cuando se cierra te redireccionaria a la pagina principal de la web, en cambio, por otro lado, tengo un apartado de panel de control de administracion de la web, donde el propietario puede publicar noticias, borrarlas, dar de alta clientes etc etc, mi problema esta en los redireccionamientos de acceso y cierre de sesion, no puedo declarar dos distintos en el security.yml, o como lo puedo hacer? Espero vuestra respuesta gracias!
Symfony Redirecciona desde el login al ultimo URL accedido (si este es interceptado por el firewall), por lo cual si el cliente accede a por ejemplo /ruta/descargas y se loguea, inmediatamente después del login lo redirige a ésa ruta, y si un admin entra a /admin lo mismo, el caso es que si un cliente intenta entrar a /admin, le mostrará la página por defecto de Access Denied
Pronto, no desesperen! 😉
El descargable cuando estará disponible?
Pronto, no desesperen, todavía no manejo la fecha, saludos 😉
Muchas gracias por el tutorial me ha servido mucho para comenzar con este framework, sobretodo para un poryecto que tengo en desarrollo
Sin embargo hay algo que aun no entiendo bien, al momento de probar la aplicacion en el entorno de producción hay alguna forma de que en las rutas no aparezca la parte de app.php/ a lo que que me refiero es pasar de una ruta como esta
http://localhost/symfony/web/app.php/hello
a esto
http://localhost/symfony/hello
Claro, para ello está el .htaccess por lo cual debes de activar el módulo Mod_Rewrite de Apache y reiniciarlo, en algunas instalaciones GNU/Linux el default host suele desactivar también la Sobre-escritura de la Url, en la cual debes de cambiar AllowObverride None por AllowOverride All y reiniciar Apache. (visto en el capítulo del controlador).
Ya con ello, elimina app.php y prueba ;-).
En el caso de IIS es diferente, pero como no recomiendo usarlo con PHP (ni lo uso) deberás por tu parte averiguar como activar la Sobre-escritura de la URL.
Oops!, se me olvidaba, también puedes crear otro virtualhost para probarlo con la url “real”, solo debes de añadir 127.0.0.1 http://www.miurlficticia.com al archivo “hosts” de tu Sistema Operativo.
corrijo: 127.0.0.1 solo_la_url_sin_el_http://
Como puedo hacer para que symfony2 este en español en ubuntu 12.04, favor podrian indicar como convertir.
Saludos,
Muy buen tutorial, la verdad que aclara mucho de este complejo framework y el proceso de seguridad.
Sigo los pasos que pones, pero cuando me voy a logear me dice “The presented password is invalid” pero no veo cuál es el problema, pues he revisado todo exhaustivamente y no sé por donde pueden venir los tiros. ¿Podrías darme una pista?
Gracias por tu sabiduría.
me sale error en la consola cuando actualiza las entidades rol y usuario por favor me puede ayudar que pasa,sera que falta algun codigo en security.ymm
c:\wamp\www\Symfony>php app/console doctrine:schema:update –force
[Symfony\Component\Config\Exception\FileLoaderLoadException]
Cannot import resource “C:\wamp\www\Symfony\app/config\security.yml” from “C:\
wamp\www\Symfony\app/config\config.yml”.
[Symfony\Component\Yaml\Exception\ParseException]
Indentation problem in “C:\\wamp\\www\\Symfony\\app\/config\\security.yml” at
line 34 (near ” access_control:”).
este es el codigo en
Symfony\app\config\security.yml
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
users:
user: { password: userpass, roles: [ ‘ROLE_USER’ ] }
admin: { password: adminpass, roles: [ ‘ROLE_ADMIN’ ] }
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/demo/secured/login$
security: false
secured_area:
pattern: ^/demo/secured/
form_login:
check_path: /demo/secured/login_check
login_path: /demo/secured/login
logout:
path: /demo/secured/logout
target: /demo/
#anonymous: ~
#http_basic:
# realm: “Secured Demo Area”
access_control:
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
#- { path: ^/_internal, roles: IS_AUTHENTICATED_ANONYMOUSLY, ip: 127.0.0.1 }
La única forma es que no implementaras el código extra en el controlador de Usuarios, revisa en la Base de datos y verifica que no esté la contraseña, lo ideal es ver un código y que el campo salt tenga valor tambien
es un error de sintaxis YML, recuerda que en YML no se deben usar TAB’s sino espacios en blanco, además intenta usar un editor como NetBeans que te permita colorear el código para detectar el error más fácilmente
¿a que componente te refieres?, el core y el profiler están en inglés y no creo que se publiquen versiones en español, en cuanto al idioma del usuario en app/parameters.ini defines el idioma por defecto en “locale”, pero ten en cuenta que el componente i18n asumirá a este por defecto, por lo que tendrás que incluir los demás archivos de idioma si quieres hacer la aplicación multilenguaje.
buen dia, me puede ayudar con el siguiente error cuando intento crear en la base de datos role y user me sale esto que no se puede actualizar porque la BD se encuentra sincronizada actualmene con entity metadadata pero no me creo las tablas role y user y no se porque
—————————————————————————————————
c:\wamp\www\Symfony>php app/console doctrine:schema:update –force
Nothing to update – your database is already in sync with the current entity met
adata.
———————————————————————————————————-
de antemano agradezco la atencion prestada
Hola alejo, he tenido el mismo problema que tu en este punto.
Si has estado siguiendo el curso hasta aquí se habremos creado un Bundle llamado MDWDemoBundle y si te fijas en el código que nos adjunta Maycol para crear los entities Role y User utiliza BlogBundle (imagino que él debia estar haciendo su propio ejemplo mientras escribia este capítulo :P)
Para mi ha funcionado cambiando en los entities
– el namespace
de: namespace MDW\BlogBundle\Entity;
por: namespace MDW\DemoBundle\Entity;
– y los parametros
donde encuentres: @param Maycol\BlogBundle\Entity\Role $userRoles
cambiarlo por: @param MDW\DemoBundle\Entity\Role $userRoles
Entonces ejecutando: php app/console doctrine:schema:update –force
Me ha funcionado a la primera.
Cuidado! hay mas referencias en el código a BlogBundle, solo tienes que cambiarlas con el nombre de Bundle que tu hayas estado utilizando.
Espero que te sirva.
Un saludo,
Silvia
Buen dia, tengo un problema con respecto a la seguridad en symfony.
Tengo dos aplicaciones web y cada aplicación tiene su seguridad separada con sus tablas y base de datos diferente, el problema esta cuando hago login en una aplicacion y quiero hacerlo en la otra me da el siguiente error:
Fatal error: Symfony\Component\Security\Core\Role\RoleHierarchy::getReachableRoles(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition “Ericsson\AplicacionesBundle\Entity\Rol” of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in C:\Apache2.2\htdocs\Ericsson\vendor\symfony\src\Symfony\Component\Security\Core\Role\RoleHierarchy.php on line 47
las dos aplicaciones tan en el mismo servidor..
necesito ayuda he realizado todo el proceso que se plantea en este tutorial. pero cuando acccedo a http://localhost/Symfony/web/app_dev.php/admin/user me sale el siguiente error: que no hay proveedor de usuario para ese usuario,pues yo cree los usuarios en la base de datos o donde habia que crear los usuarios
——————————————————————————————————–
There is no user provider for user “Symfony\Component\Security\Core\User\User”.There is no user provider for user “Symfony\Component\Security\Core\User\User”.
————————————————————————————————
agradezco de antemano la atencion prestada
Tengo una base de datos que esta en produccion y ademas en reevision para adaptarla y dar mas funcionamiento. Mi pregunta es la siguiente. ¿Es posible adaptar todo esto aprendido en los cursos cuando uno tiene un proyecto que ya lleva años pero siempre inconcluso y ademas con muchos datos que se deben reestructurar?. Es una pequeña base de datos en access que fue creciendo y ya tiene 20 años de datos dentro pero nunca les intereso replantear toda la base ni sus servicios?. Soy administrativo avanzado con manejo de base de datos en access y mysql, php, visual basic 6 y he estudiado por mi cuenta programacion orientada a objetos. Me da la sensacion que para hacer utilizar y explotar todas estas herramientas uno deberia encarar el trabajo sabiendo los limites y no a media marcha. ¿que me dices tu a esto?. Tu sabes que soy administrativo y fui implementando soluciones sin tener un apoyo institucional de donde trabajo. Atodos les gusta hacer las cosas rapido pero nadie quiere invertir en nada. Tengo una aplicacion access y una intranet que muestra informes. Desde access tambien saco listados complejos.
Tengo una consulta, esto me funciono todo correctamente, muchas gracias. Mi panorama es el siguiente, yo realice la conexión con la base de datos, este se loguea correctamente con ella, lo que no he logrado es lo siguiente:
– Obtener los datos se la sesion activa, nombre de usuario fecha de logeo, etc.
– Cerrar sesion, implemente en la twig dentro de un boton : path(‘logout’) y en security:
logout:
path: /logout
delete_cookies:
target: /login
invalidate_session: false
El problema se da al momento, por ejemplo de cerrar el explorador, y volver a entrar este sigue logeado, al pasar un rato, ciertos minutos, me gustaría que se cerrara la sesión, y al presionar el botón y cerrar la sesión, esta se debería cerrar pero al acceder al index esta sigue abierta.
Podrían ayudarme por favor, lo agradecería mucho.
Saludos.
tengo el mismo problema silviaez he comprobado tu respuesta pero da el mismo
yo tengo un problema y no se resolverlo el problema es que cuando pongo el comandophp app\console doctrine:generate:crud – me pregunta el nombre – yo pongo e nombre yo pongo nombre MDWwebBunde:User como del manual y me da error class MDW \webBundle\Entity\User is not valid cual puede ser el problema ¿?
Mi consulta es la siguiente:
En un formulario, quiero que se muestren ciertos campos dependiendo del role con el que entra el usuario. Por ejemplo, si el usuario tiene el role admin puede ver todos los campos de un formulario, pero si tiene role usuario, solo puede ver algunos campos del mismo formulario para la carga del mismo.
Espero se haya entendido, agradezco la ayuda
Mi consulta es la siguiente:
He creado los dos reles ROLE_ADMIN y ROLE_USER, un usuario con ROLE_ADMIN y un usuario con ROLE_USER, al autentificarse no me reconece ninguno de los dos, cuando creo los usuarios desde phpMyAdmin, hay que seleccionar alguna funcion para el campo password y/o salt. Por favor, alguien me puede ayudar.
Gracias.
Realice el ejemplo de este capitulo completo y todo funciono correctamente, pero al final, cuando me logeo en la aplicación con cualquier usuario me aparece este error
Fatal error: Call to a member function getRole() on a non-object in C:\xampp\htdocs\symfony\vendor\symfony\src\Symfony\Component\Security\Core\Role\RoleHierarchy.php on line 47
por lo que e visto este error es a causo de php 5.4
no se como solucionarlo, me prodrian ayudar. Gracias
Con el ejercicio 1 me sale el siguiente error, donde prodria estar la falla.
Unable to find template “MDWDemoBundle:Default:articulos.html.twig”
saludos
Buenas. Agradezco el tutorial, me ha ayudado mucho. Tengo el siguiente problema cuando edito el archivo security.yml y trato de acceder a http://localhost/Symfony/web/app_dev.php/admin/login me sale el siguiente error (muy feo por cierto):
InvalidConfigurationException: Unrecognized options “user_db” under “security.encoders.providers”
in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/ArrayNode.php line 268
at ArrayNode->normalizeValue() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/BaseNode.php line 195
at BaseNode->normalize() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/PrototypedArrayNode.php line 225
at PrototypedArrayNode->normalizeValue() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/BaseNode.php line 195
at BaseNode->normalize() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/ArrayNode.php line 260
at ArrayNode->normalizeValue() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/BaseNode.php line 195
at BaseNode->normalize() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/Processor.php line 35
at Processor->process() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/Config/Definition/Processor.php line 52
at Processor->processConfiguration() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/HttpKernel/DependencyInjection/Extension.php line 101
at Extension->processConfiguration() in /var/www/Symfony/vendor/symfony/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php line 53
at SecurityExtension->load() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php line 42
at MergeExtensionConfigurationPass->process() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/HttpKernel/DependencyInjection/MergeExtensionConfigurationPass.php line 39
at MergeExtensionConfigurationPass->process() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php line 119
at Compiler->compile() in /var/www/Symfony/vendor/symfony/src/Symfony/Component/DependencyInjection/ContainerBuilder.php line 437
at ContainerBuilder->compile() in /var/www/Symfony/app/bootstrap.php.cache line 872
at Kernel->buildContainer() in /var/www/Symfony/app/bootstrap.php.cache line 783
at Kernel->initializeContainer() in /var/www/Symfony/app/bootstrap.php.cache line 517
at Kernel->boot() in /var/www/Symfony/app/bootstrap.php.cache line 548
at Kernel->handle() in /var/www/Symfony/web/app_dev.php line 27
He buscado y no aparece ninguna coincidencia en google. Me pueden ayudar.? Gracias
Ya pude resolver. Pero ahora hay ago que no entiendo, cuando ingreso nombre de usuario y contraseña en el ejercicio se define a donde ingresa el usuario.? estoy nueva con symfony disculpen, pero no entiendo en qué sitio se indica la página a la que debe ir el usuario una vez que logueado. Espero que alguien me pueda ayudar. Gracias
hola Maycol, muy bueno el tuto… sigo todos los pasos, pero al querer entrar en localhost/app_dev.php/login me sale este error: Unable to find template MyBundle:Security:login.html.twig”. 500 Internal Server Error – InvalidArgumentException
3 linked Exceptions:
y cuando kiero entrar a localhost/app_dev.php/admin/user me sale este error :
No route found for “GET /admin/user”
ayuda porfas… ya he mirado todos los pasos varias veces y no logro solucionarlo…
Muchas gracias
Javier
listo…fue error mio al crear login.html.twig le puse un espacio en blanco al final del nombre.. por eso nunca lo encontraba…….
gracias
estoy siguiendo la guía y cuando trato de hacer login con los usuarios que creo me sale este error:
Fatal error: Call to a member function getRole() on a non-object in C:\xampp\htdocs\Symfony\vendor\symfony\src\Symfony\Component\Security\Core\Role\RoleHierarchy.php on line 47
…todo lo demás me sale bien.
buenas me gustaría me ayudaran con un problema, como tal la aplicación funciona perfectamente el problema que tengo o no se que es lo que debo hacer para continuar va en esto:
cuando realizo el Paso 3: Creando el esquema de seguridad ya sabiendo que puedo crear, editar… desde los cruds web voy a la ruta especifica para acceder al nuevo crud para realizar el logeo en la aplicación
ponga lo que ponga en las
en la direccion http://localhost/“”/app_dev.php/QM/admin/login
y al dar en el botón para que este envié la información el único cambio que veo es que
la dirección http://localhost/“”/app_dev.php/QM/admin/login
CAMBIA A ESTA NUEVA DIRECCIÓN SIN DAR MENSAJE DE ERROR NI NADA
http://localhost/“”/app_dev.php/QM/admin/login_check
y yo deseo que me redirija a la dirección donde se encuentra el crud de User que se crea en este tutorial por ejemplo.
Muy bueno el articulo y sus respuestas de Maycol, espero pueda indicarme a mi como hacer.
Yo quisiera que mi app validara el usuario y el password viendo si la propia combinacion se conecta al Gestor de Base de Datos. Me explico mejor: Mi user y password para conectarme a la base de datos PostgreSQL son: user “postgres” y password “adminpgsql”, me gustaria que symfony2 me logueara en el sistema si el usuario y el password son estos. Esto es posible ??
Me puede decir como proceder ???
Desde ya muchas gracias…
Hola, excelente toda la guia, me resulto muy util. Tengo un problema, y quizas es muy basico lo que voy a preguntar pero recien estoy arrancando y no me doy mucha maña con el tema: como se hace para generar una pagina luego de que se creo un usuario, donde se recuperen los datos del usuario que se acaba de crear y publique un texto que diga “el usuario ‘tal’ (con el campo username por dar un ejemplo cualquiera) se creo exitosamente”. Es decir como recupero el usuario y plasmo sus datos en una pagina. El mismo problema tengo para un usuario que se acaba de loguear, como recupero el usuario logueado y que publique “el usuario x se ha logueado exitosamente”. Espero que alguno pueda ayudarme, desde ya muchisimas gracias.
Amado, estoy como tu, has podido resolver el problema? te agradecería si tienes la solución que la compartas.
gracias.