symfony3 authentication y authorization con base de datos

es similar a la que se hace en memoria pero cambiamos el provider in memory por
uno que tenga seteado nuestra clase entity de Usuario y el campo por el que se validara
el nombre de usuario ingresado al loguearse (en este caso se usa pero tambien podria ser el campo email)

en app/config/security.yml

security:

    # https://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
    providers:
        my_db_provider:
          entity:
            class: AppBundle:Usuario
            property: username
    encoders:
        AppBundle\Entity\Usuario:
          algorithm: bcrypt
          cost: 12

    firewalls:
        # disables authentication for assets and the profiler, adapt it according to your needs
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false

        main:
            pattern: ^/*
            anonymous: ~
            # activate different ways to authenticate
           
            provider: my_db_provider

            # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
            http_basic: ~

            # https://symfony.com/doc/current/security/form_login_setup.html
            #form_login: ~
            form_login:
                login_path: login
                check_path: login
               
            logout:
                path:   /logout
                target: /
 

nota:

no olvidar poner en routing.yml

logout:
  path: /logout


necesitamos 2 entities: Usuario y Rol

por facilidad los podemos crear via consola

php bin/console doctrine:generate:entity --entity AppBundle:Usuario -n
php bin/console doctrine:generate:entity --entity AppBundle:Rol -n

la relacion entre estas clases es de ManyToMany

Un usuario puede tener muchos roles y un rol puede ser de muchos usuarios

class Usuario implements UserInterface

id
username
password
isActive

/**
     * @ORM\ManyToMany(targetEntity="Rol", mappedBy="usuarios")
     ")
     */
    private $roles;


    public function __construct() {
     
        $this->roles= new ArrayCollection();
    }

public function eraseCredentials()
    {}

    public function getSalt()
    {
        return null;
    }

    public function getRoles() {
        $roles = array();
        foreach ($this->roles as $rol) {
            $roles[] = $rol->getNombre();
        }
        return $roles;
    }


al implementar UserInterface, se debera implementar los metodos eraseCredentials y getSalt

getRoles...devuelve un arreglo con los nombres de los roles que el usuario tiene asignado, ya que symfony hace la authorization contra los nombres de los roles como strings.

class Rol
{
    private $id;

    private $nombre;
    /**
    * @ORM\ManyToMany(targetEntity="Usuario", inversedBy="roles", cascade={"persist","remove"})
    */
    private $usuarios;
   
    public function __construct() {
     
        $this->usuarios = new ArrayCollection();
    }


en una relacion ManyToMany el owning side es quien tiene inversedBy y puede ser cualquiera de las 2 clases.


y eso seria todo.


symfony creara automaticamente una 3era tabla llamada rol_usuario con los campos rol_id y usuario_id




tip: si se quiere validar tanto por username o email, entonces debemos quitar la linea property de security.yml

y hacer que nuestra clase UsuarioRepository implemente UserLoaderInterface

y sobreescribimos el metodo loadUserByUsername


class UsuarioRepository extends \Doctrine\ORM\EntityRepository implements UserLoaderInterface
{
    public function loadUserByUsername($username)
    {
        return $this->createQueryBuilder('u')
        ->where('(u.username = :username OR u.email = :email) AND u.isActive=1')
        ->setParameter('username', $username)
        ->setParameter('email', $username)
        ->getQuery()
        ->getOneOrNullResult();
    }

}

para obtener passwords encriptados segun el encoder que estamos usando bcrypt (cost=12)
y asi crear usuarios en nuestra tabla usamos el siguiente comando por consola

php -r "echo password_hash('tupassword', PASSWORD_BCRYPT, ['cost' => 12]) . PHP_EOL;"





No hay comentarios:

Publicar un comentario

linux ubuntu mint actualizar chrome

 desde una terminal: $ sudo apt update $ sudo apt install google-chrome-stable