Authentication with Symfony. How to do authentication (simple)

0

I have a problem here.

I'm in a project using symfony (very good Framework), however I've seen some complexities of how it does authentication. I was able to login, but at the time of entering the home, as it is protected in the file of segirança for only ROLE_ADMIN access, I would like to know of you, in symfony3, how do I recover this permission for my user, the user already has the implementations all, but symfony does not see it as ROLE_ADMIN. Follow the code.

Controller

public function loginAction(Request $request)
{
  if ($request->get('usuario')) {
    $usuario = $request->get('usuario');
    $senha = $request->get('senha');

    $user_manager = $this->getDoctrine()->getRepository('AppBundle:Usuarios');
    $factory = $this->get('security.encoder_factory');

    $user = $user_manager->loadUserByUsername($usuario);
    $encoder = $factory->getEncoder($user);
    $salt = $user->getSalt();

    if($encoder->isPasswordValid($user->getPassword(), $senha, $salt)) {
      return $this->redirect('/home');
    }
    else {
      $this->addFlash('error', 'Usuario ou senha não não encontrados!');
      return $this->redirect('/');
    }
  }

  $authenticationUtils = $this->get('security.authentication_utils');
  $error = $authenticationUtils->getLastAuthenticationError();
  $lastUsername = $authenticationUtils->getLastUsername();

  return $this->render(
      'login/index.html.twig',
      array(
          'last_username' => $lastUsername,
          'error'         => $error,
      )
  );
}

Repository

class UserRepository extends EntityRepository implements UserLoaderInterface
{
    public function loadUserByUsername($username)
    {
        $user = $this->createQueryBuilder('u')
            ->where('u.usulogin = :usulogin')
            ->setParameter('usulogin', $username)
            ->getQuery()
            ->getOneOrNullResult();

        if (null === $user) {
            $message = sprintf(
                'Unable to find an active admin AppBundle:User object identified by "%s".',
                $username
            );
            throw new UsernameNotFoundException($message);
        }

        return $user;
    }
}

Entity

class Usuarios implements UserInterface, \Serializable
{
   //codigos não coloquei a classe interira, apenas a implemetação da interface, para ficar menor, porem garanto estar de acordo com a doc.
/**
* inicio das implementações da inteface
*/
public function getUsername()
   {
       return $this->usunom;
   }

   public function getRoles()
   {
       return array('ROLE_ADMIN');
   }

   public function getPassword()
   {
    return  $this->ususenha;
   }
   public function getSalt()
   {
     return null;
   }
   public function eraseCredentials()
   {
   }

    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->usuid,
            $this->usunom,
            $this->ususenha,
            // ver la sección salt debajo
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list (
          $this->usuid,
          $this->usunom,
          $this->ususenha,
            // ver la sección salt debajo
            // $this->salt
        ) = unserialize($serialized);
    }
}

Security.yml

# app/config/security.yml
security:
    encoders:
        AppBundle\Entity\Usuarios:
            algorithm: bcrypt

    providers:
        our_db_provider:
            entity:
                class: AppBundle:Usuarios

    firewalls:
        main:
            provider: our_db_provider

            anonymous: true

            form_login:
                login_path: /login
                check_path: /

            logout:
                path: /logout
                target: /login

            remember_me:
                secret:   '%secret%'
                lifetime: 604800 # 1 week in seconds
                path: /

    access_control:
      - { path: ^/home, roles: ROLE_ADMIN }
    # ...

all Help is welcome ...

    
asked by anonymous 09.09.2017 / 08:49

1 answer

0

Problem solved, as I did not get answers, I decided to do it myself and in fact it is very simple, here is the resolution for those who want.

Controller

<?php

namespace AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use AppBundle\Entity\Usuarios;
use AppBundle\Repository\UserRepository;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;

class LoginController extends Controller
{
  /**
   * @Route("/",name="authentication");
   */
   public function indexAction()
   {
     $authenticationUtils = $this->get('security.authentication_utils');
     $error = $authenticationUtils->getLastAuthenticationError();
     $lastUsername = $authenticationUtils->getLastUsername();

     return $this->render(
         'login/index.html.twig',
         array(
             'last_username' => $lastUsername,
             'error'         => $error,
         )
     );
   }

   /**
    * @Route("/login", name="login");
    */
    public function loginAction(Request $request)
    {
    }

    /**
     * @Route("/logout");
     */
     public function logoutAction()
     {
     }

}

In the user entity implement this interface

class Usuarios implements UserInterface, \Serializable
{
    /**
* inicio das implementações
*/
public function getUsername()
   {
       return $this->usunom;
   }

   public function getRoles()
   {
       return array('ROLE_ADMIN');
   }

   public function getPassword()
   {
    return  $this->ususenha;
   }
   public function getSalt()
   {
     return null;
   }
   public function eraseCredentials()
   {
   }

    /** @see \Serializable::serialize() */
    public function serialize()
    {
        return serialize(array(
            $this->usuid,
            $this->usunom,
            $this->ususenha,
            // ver la sección salt debajo
            // $this->salt,
        ));
    }

    /** @see \Serializable::unserialize() */
    public function unserialize($serialized)
    {
        list (
          $this->usuid,
          $this->usunom,
          $this->ususenha,
            // ver la sección salt debajo
            // $this->salt
        ) = unserialize($serialized);
    }
}

Create a folder inside your Bundle named Repository and create the following class inside it

<?php
namespace AppBundle\Repository;

use Symfony\Bridge\Doctrine\Security\User\UserLoaderInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Doctrine\ORM\EntityRepository;

class UserRepository extends EntityRepository implements UserLoaderInterface
{
    public function loadUserByUsername($username)
    {
        $user = $this->createQueryBuilder('u')
            ->where('u.usulogin = :usulogin')
            ->setParameter('usulogin', $username)
            ->getQuery()
            ->getOneOrNullResult();

        if (null === $user) {
            $message = sprintf(
                "Usuário $username, não foi encontrado!"
            );
            throw new UsernameNotFoundException($message);
        }

        return $user;
    }
}

 ?>

Create a folder inside your Bundle called Security and create the following class inside it

<?php
namespace AppBundle\Security;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Core\Security;

class FormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
    private $router;
    private $encoder;

    public function __construct(RouterInterface $router, UserPasswordEncoderInterface $encoder)
    {
        $this->router = $router;
        $this->encoder = $encoder;
    }

    public function getCredentials(Request $request)
    {
        if ($request->getPathInfo() != '/login') {
          return;
        }

        $email = $request->request->get('usuario');
        $request->getSession()->set(Security::LAST_USERNAME, $email);
        $password = $request->request->get('senha');

        return [
            'usulogin' => $email,
            'ususenha' => $password,
        ];
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $email = $credentials['usulogin'];

        return $userProvider->loadUserByUsername($email);
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        $plainPassword = $credentials['ususenha'];
        if ($this->encoder->isPasswordValid($user, $plainPassword)) {
            return true;
        }

        throw new BadCredentialsException('Erro ao autenticar!');
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
    {
        $url = $this->router->generate('home');

        return new RedirectResponse($url);
    }

    public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
    {
       $request->getSession()->set(Security::AUTHENTICATION_ERROR, $exception);

       $url = $this->router->generate('authentication');

       return new RedirectResponse($url);
    }

    protected function getLoginUrl()
    {
        return $this->router->generate('authentication');
    }

    protected function getDefaultSuccessRedirectUrl()
    {
        return $this->router->generate('home');
    }

    public function supportsRememberMe()
    {
        return false;
    }
}

Now edit security.yml

# app/config/security.yml
security:
    encoders:
        AppBundle\Entity\Usuarios:
            algorithm: bcrypt

    providers:
        our_db_provider:
            entity:
                class: AppBundle:Usuarios

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

       main:
            anonymous: ~
            guard:
                authenticators:
                    - app.form_login_authenticator
            logout:
                path: /logout
                target: /

            remember_me:
                secret:   '%secret%'
                lifetime: 604800 # 1 week in seconds
                path: /

    access_control:
      - { path: ^/home, roles: ROLE_ADMIN }
      - { path: ^/cadastrarUsuario, roles: ROLE_ADMIN }
    # ...

and services.yml

# Learn more about services, parameters and containers at
# https://symfony.com/doc/current/service_container.html
parameters:
    #parameter_name: value

services:
    # default configuration for services in *this* file
    app.form_login_authenticator:
        class: AppBundle\Security\FormLoginAuthenticator
        arguments: ["@router", "@security.password_encoder"]
    _defaults:
        # automatically injects dependencies in your services
        autowire: true
        # automatically registers your services as commands, event subscribers, etc.
        autoconfigure: true
        # this means you cannot fetch services directly from the container via $container->get()
        # if you need to do this, you can override this setting on individual services
        public: false

    # makes classes in src/AppBundle available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    AppBundle\:
        resource: '../../src/AppBundle/*'
        # you can exclude directories or files
        # but if a service is unused, it's removed anyway
        exclude: '../../src/AppBundle/{Entity,Repository,Tests}'

    # controllers are imported separately to make sure they're public
    # and have a tag that allows actions to type-hint services
    AppBundle\Controller\:
        resource: '../../src/AppBundle/Controller'
        public: true
        tags: ['controller.service_arguments']

    # add more services, or override services that need manual wiring
    # AppBundle\Service\ExampleService:
    #     arguments:
    #         $someArgument: 'some_value'

And just to test, it worked out right here.

Using security.yml and these implementations, the symphony itself takes care of doing security. If you want to protect your routes after logging in, that is to not access them when they are not logged in, simply add the route in your security.yml

access_control:
      - { path: ^/home, roles: ROLE_ADMIN }
      - { path: ^/cadastrarUsuario, roles: ROLE_ADMIN }

Hugs.

    
10.09.2017 / 21:14