Symfony2 desde 0: Login y registro

Ahora veremos como hacer un login y registro con Symfony2. En el post anterior definimos la plantilla en la que montamos el formulario de login. ¡OJO! Con el name de username y password en el formulario de login, es necesario que delante tengan un guión bajo.

Ahora montaremos el sistema de autenticación que nos proporciona Symfony2.

Definiremos las rutas que necesitaremos hasta ahora en el fichero routing.yml de nuestro bundle:

inicio:
    pattern:  /
    defaults: { _controller: WebBlogBundle:Posts:index, page:1 }

home:
    pattern:  /inicio/{page}
    defaults: { _controller: WebBlogBundle:Posts:index, page:1 }
    
registro:
    pattern:  /registro
    defaults: { _controller: WebBlogBundle:Default:index }

#Rutas para la autenticacion
login:
  pattern: /login
  defaults: { _controller: WebBlogBundle:Default:login }

login_check:
   pattern: /login_check

logout:
  pattern: /logout

Ahora configuraremos el fichero app/config/security.yml, aquí cofiguramos las entidades y las rutas que entran en juego en la autenticación y tambien la ACL de Symfony. En nuestro caso lo dejaremos así:

security:
    firewalls:
        identificarse:
          pattern: ^/*          
          anonymous: ~
          provider: users
          form_login:
            login_path: login
            check_path: /login_check
          logout:
            path: logout
            target: /

    providers:
        users:
            entity: { class: Web\BlogBundle\Entity\Users, property: email }
    
    access_control:
        - { path: ^/registro, roles: IS_AUTHENTICATED_ANONYMOUSLY}
    
    encoders:
        Web\BlogBundle\Entity\Users: { algorithm: sha512, iterations: 10 }

El siguiente paso es modificar la entidad para que funcione automáticamente con el componente de seguridad. Modificamos el fichero src/Web/BlogBundle/Entity/Users.php y añadimos lo siguiente.

<?php

namespace Web\BlogBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Doctrine\Common\Collections\ArrayCollection;
use Symfony\Component\Security\Core\User\UserInterface;


/**
 * Users
 */
class Users implements UserInterface
{
    
    //Implementacion de la interfaz de roles
    public function equals(UserInterface $users){
        return $this->getEmail()==$users->getUsername();
    }
    
    public function eraseCredentials() {
        return false;
    }
    
    public function getRoles() {
       //return array("ROLE_USUARIO");
        return array($this->getRole());
    }
    
    public function getUsername() {
        return $this->getEmail();
    }
    
    public function getSalt() {
        return false;
    }
    //Fin de la definicion de clases de la interface de roles

Ahora crearemos el formulario de registro. Web\BlogBundle\Form\Type\RegistroType.php

<?php

namespace Web\BlogBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Doctrine\ORM\EntityRepository;

class RegistroType extends AbstractType {

    public function buildForm(FormBuilderInterface $builder, array $options) {
        $builder->add('name', 'text', array("label" => "Nombre: ",
                    "required" => false,
                    "attr" => array('class' => 'form-control')))
                
                ->add('surname', 'text', array("label" => "Apellido: ",
                    "required" => false,
                    "attr" => array('class' => 'form-control')))
                
                ->add('email', 'email', array("label" => "Correo electronico: ",
                    "required" => false,
                    "attr" => array('class' => 'form-control')))
                
                ->add('password', 'repeated', array(
                    'type' => 'password',
                    'invalid_message' => 'Las contraseñas no son iguales, repitelo',
                    'required' => true,
                    'first_options' => array('label' => 'Contraseña: ',"attr" => array('class' => 'form-control')),
                    'second_options' => array('label' => 'Repetir contraseña: ',"attr" => array('class' => 'form-control'))))
                
                ->add('Registrarse', 'submit',array("attr" => array('class' => 'btn btn-success')));
    }

    public function getName() {
        return 'Registro';
    }

}

?>

Para hacer el login y registro en Symfony2 utilizaremos DefaultController.php

<?php

namespace Web\BlogBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Web\BlogBundle\Entity\Users;
use Web\BlogBundle\Form\Type\RegistroType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\SecurityContext;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;

class DefaultController extends Controller {

    private $session;

    public function __construct() {
        //Cargamos el componente de sesion en todos los metodos
        $this->session = new Session();
    }

    public function indexAction(Request $request) {
        //Instanciamos el obejeto usuario
        $user = new Users();
        
        //Creamos el formulario de Registro
        $registro_form = $this->createForm(new RegistroType(), $user);

        //Recogemos los datos
        $registro_form->handleRequest($request);

        //Si el formulario está enviado
        if ($registro_form->isSubmitted()) {
            //Consigue los datos
            $nombre = $registro_form->get('name')->getData();
            $apellidos = $registro_form->get('surname')->getData();
            $email = $registro_form->get('email')->getData();

            //Cifra la contraseña
            $factory = $this->get('security.encoder_factory');
            $encoder = $factory->getEncoder($user);
            $password = $encoder->encodePassword($registro_form->get('password')->getData(), $user->getSalt());

            //Seteamos los atributos
            $user->setName($nombre);
            $user->setSurname($apellidos);
            $user->setEmail($email);
            $user->setPassword($password);
            $user->setDescription("Describete");
            $user->setImage("default_avatar.png");
            $user->setRole("ROLE_USUARIO");
        }

        //Si el formulario es valido
        if ($registro_form->isValid()) {
            
            $repositorio = $this->getDoctrine()->getRepository('WebBlogBundle:Users');

            $email_existe = false;

            if ($email_existe == false) {
                //Guarda el usuario en base de datos
                $em = $this->getDoctrine()->getManager();
                $persist = $em->persist($user);
                $flush = $em->flush();
                
                //generar flasdata
                $this->session->getFlashBag()->add('info', '¡Enhorabuena! Te has registrado correctamente');
                
                //Redirigir
                return $this->redirect($this->generateURL('registro'));
            } else {
                //genera una sesion flasdata
                $this->session->getFlashBag()->add('info', 'Email o nick duplicado intentalo de nuevo');
            }
        }

        //Categorias
        $em = $this->getDoctrine()->getEntityManager();
        $categoryRepository=$em->getRepository("WebBlogBundle:Categories");
        $categories=$categoryRepository->findAll();

        //Renderizar vista y pasar formulario
        return $this->render('WebBlogBundle:Default:registro.html.twig', 
                array('registro_form' => $registro_form->createView(),
                    "categories"=>$categories
                ));
    }
    
    
    public function loginAction(Request $request){ 
        // Si la autenticación falla que nos lleve a registro y si no a la home
        if($this->session->get(SecurityContext::AUTHENTICATION_ERROR)){
           $this->session->getFlashBag()->add('login', 'Introduce unas credenciales correctas');
           return $this->redirect($this->generateURL('registro'));
        }else{
            if($this->get('security.context')->isGranted('ROLE_USUARIO')){
                return $this->redirect($this->generateURL('home'));
            }
        }
    }

}

La vista de registro src/Web/BlogBundle/Resources/views/Default/registro.html.twig hereda de la plantilla y quedaría así:

{% extends "::plantilla.html.twig" %}

{%block categorias%}
        {% for category in categories %}
             <li><a href="#">{{ category.name }}</a></li>
        {% endfor %}
{%endblock%}

{% block content %}
<div class="col-lg-8 col-md-8 col-sm-8 col-xs-8">
<h3>Registrate</h3>
<hr/>
{% for mensaje in app.session.flashbag().get('info') %}
<p class="info">{{ mensaje }}</p>
{% endfor %}
<form action="" method="post" {{ form_enctype(registro_form) }}>
    {{ form_widget(registro_form) }}
    {{ form_errors(registro_form) }}
</form>
</div>
{%endblock%}

Con esto ya tendríamos el login y registro en Symfony2.

Victor

Autor: Victor

Desarrollador web - Formador online - Blogger

Compartir este post

2 Comentarios

  1. En una RESTful API la construcción es la misma para un login?

    Responder
    • No, en un api restful habría que utilizar una autenticación mediante tokens con JWT por ejemplo.

      Saludos 😉

      Responder

Poner un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *