Problem with error checking at login time

Asked

Viewed 26 times

0

I’m having a problem checking login errors with symfony 4.

I’m trying to log into the system, only I don’t know why form, even being with the method POST sending GET and because of that I can’t verify whether the form has been sent, no information comes, BUT I can log into the system.

If I change in the security.yaml the tag of the form_login the check_path of login for /login I can do the checks, but I can’t log in.

Follow my code below:

security.yaml:

security:
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
    main:
        entity: { class: App\Entity\User, property: username }

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    main:
        anonymous: true


        # activate different ways to authenticate

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

        form_login:
            login_path: login
            check_path: /login
            default_target_path: admin
            always_use_default_target_path: true

        # https://symfony.com/doc/current/security/form_login_setup.html
        logout:
            path: /logout
            target: /admin/login


# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
    - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/recoveryPassword, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/forgotPassword, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin, roles: ROLE_ADMIN }

encoders:
    App\Entity\User:
        algorithm: bcrypt
        cost: 12

LoginController.php:

<?php
namespace App\Controller;

use App\Entity\User;
use App\Utils\AntiSQL;
use App\Utils\Password;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;

class LoginController extends Controller
{

    /**
     * @Route("/admin/login", name="login")
     * @Template("login/login.html.twig")
     * @param Request $request
     *
     * @return array
     */
    public function login(Request $request)
    {

        if($request->getMethod() == 'POST'):

            $data = AntiSQL::filterAll($request->request->all());

            $em = $this->getDoctrine()->getManager();
            $user = $em->getRepository(User::class)->findOneByUsername($data['_username']);


            // Verifica se algum campo está em branco
            if(empty($data['_username']) OR empty($data['_password'])):
                return [
                    'mensagem' => [
                        'texto' => 'Usuário ou senha em branco',
                        'icone' => 'fas fa-exclamation-triangle',
                        'class' => 'alert-danger',
                        'alerta' => 'Alerta'
                    ]
                ];
            endif;

            // Verifica se o usuário existe
            if($user->getUsername() == null):
                return [
                    'mensagem' => [
                        'texto' => 'Usuário ou senha inválidos',
                        'icone' => 'fas fa-exclamation-triangle',
                        'class' => 'alert-danger',
                        'alerta' => 'Alerta'
                    ]
                ];
            endif;

            // Verifica se a senha e o token são válidos
            if(Password::verifyPassword($data['_password'], $user->getPassword()) OR $this->isCsrfTokenValid("form_login", $data['_token']) == false ):

            endif;
        endif;

        return [
            'mensagem' => []
        ];
    }

}

login.html.twig:

{% extends 'layout/base_login.html.twig' %}

{% block content %}
<form action="{{ path('login') }}" method="POST" class="smart-form client-form">
    <header >
        Acessar Painel de Controle
    </header>
    <fieldset>
        <section>
            <label class="label">Usuário</label>
            <label class="input"><i class="icon-append fa fa-user txt-color-teal"></i>
                <input type="text" name="_username" id="username" autofocus>
                <b class="tooltip tooltip-top-right"><i class="fa fa-user txt-color-teal" ></i> Digite seu Usuário</b></label>
        </section>

        <section>
            <label class="label">Senha</label>
            <label class="input"> <i class="icon-append fa fa-lock txt-color-teal"></i>
                <input type="password" name="_password" id="password">
                <b class="tooltip tooltip-top-right"><i class="fa fa-lock txt-color-teal"></i> Digite sua Senha</b> </label>
            <div class="note">
                <a href="forgotpassword.html" class="txt-color-teal">Esqueceu a Senha?</a>
            </div>
            <input type="hidden" name="_token" value="{{ csrf_token('form_login') }}">
        </section>
    </fieldset>
    <footer>
        <button type="submit" class="btn bg-color-teal txt-color-white">
            Entrar
        </button>
    </footer>
</form>
{% endblock %}
  • Instead of using an if to know if it’s a POST or GET, you can create two actions one for the POST and one for the GET and define in the Annotation which of the two methods it is. In my opinion the code is more "clean" so and easier to work with.

  • You can use Symfony Forms and avoid having to put that check if the fields are empty or not with constraints in the form.

  • Instead of using Repository to check whether or not one exists in the controller you can abstract that logic with a Paramconverter.

1 answer

1

In your Controller, you have to say that route accepts POST type, otherwise you will use GET by default:

/**
 * @Route("/admin/login", name="login", methods={"POST"})
 */

Vide Symfony Docs

Browser other questions tagged

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