Symfony authentication. How to authenticate (simple)

Asked

Viewed 446 times

0

I got a problem here.

I’m on a project using symfony (very good Framework), but I’ve seen some complexities of how it authenticates. I was able to log in, however 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 from you, in symfony3, how to recover this permission for my user, the user already has all implementations, however symfony does not see it as ROLE_ADMIN. Follows 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...

1 answer

0


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

Controler

<?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 within your Bundle called Repository and create the following class within 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 within your Bundle called Security and create the following class within 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 the 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 the 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 testing, here it went right.

Using security.yml and these implementations, Symphony itself takes care of security. If you want to protect your routes after logging in, that is to say, do not log in when you are not logged in, just add the route in your security.yml

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

Hugs.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.