Зарегистрированный пользователь все еще имеет пустой сеанс symfony 5 - PullRequest
0 голосов
/ 30 января 2020

У меня проблемы с отображением имени пользователя после входа в систему с помощью Symfony 5, и я выяснил, что объект сеанса остается пустым после того, как пользователь вошел в систему, это мой AuthAuthenticator. php file

<?php

namespace App\Security;

use App\Entity\User;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\CustomUserMessageAuthenticationException;
use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Csrf\CsrfToken;
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\Security\Guard\PasswordAuthenticatedInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;

class AuthAuthenticator extends AbstractFormLoginAuthenticator implements
    PasswordAuthenticatedInterface
{
    use TargetPathTrait;

    private $entityManager;
    private $urlGenerator;
    private $csrfTokenManager;
    private $passwordEncoder;

    public function __construct(
        EntityManagerInterface $entityManager,
        UrlGeneratorInterface $urlGenerator,
        CsrfTokenManagerInterface $csrfTokenManager,
        UserPasswordEncoderInterface $passwordEncoder
    ) {
        $this->entityManager = $entityManager;
        $this->urlGenerator = $urlGenerator;
        $this->csrfTokenManager = $csrfTokenManager;
        $this->passwordEncoder = $passwordEncoder;
    }

    public function supports(Request $request)
    {
        return 'app_login' === $request->attributes->get('_route') &&
            $request->isMethod('POST');
    }

    public function getCredentials(Request $request)
    {
        $credentials = [
            'matricule' => $request->request->get('matricule'),
            'password' => $request->request->get('password'),
            'csrf_token' => $request->request->get('_csrf_token')
        ];
        $request
            ->getSession()
            ->set(Security::LAST_USERNAME, $credentials['matricule']);

        return $credentials;
    }

    public function getUser($credentials, UserProviderInterface $userProvider)
    {
        $token = new CsrfToken('authenticate', $credentials['csrf_token']);
        if (!$this->csrfTokenManager->isTokenValid($token)) {
            throw new InvalidCsrfTokenException();
        }

        $user = $this->entityManager
            ->getRepository(User::class)
            ->findOneBy(['matricule' => $credentials['matricule']]);

        if (!$user) {
            // fail authentication with a custom error
            throw new CustomUserMessageAuthenticationException(
                'The Member Matricule could not be found.'
            );
        }

        return $user;
    }

    public function checkCredentials($credentials, UserInterface $user)
    {
        return $this->passwordEncoder->isPasswordValid(
            $user,
            $credentials['password']
        );
    }

    /**
     * Used to upgrade (rehash) the user's password automatically over time.
     */
    public function getPassword($credentials): ?string
    {
        return $credentials['password'];
    }

    public function onAuthenticationSuccess(
        Request $request,
        TokenInterface $token,
        $providerKey
    ) {
        if (
            $targetPath = $this->getTargetPath(
                $request->getSession(),
                $providerKey
            )
        ) {
            return new RedirectResponse($targetPath);
        }

        return new RedirectResponse($this->urlGenerator->generate('home'));
    }

    protected function getLoginUrl()
    {
        return $this->urlGenerator->generate('app_login');
    }
}

это файл security.yml

security:
  encoders:
    App\Entity\User:
      algorithm: auto

  # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
  providers:
    # used to reload user from session & other features (e.g. switch_user)
    app_user_provider:
      entity:
        class: App\Entity\User
        property: matricule
  firewalls:
    dev:
      pattern: ^/(_(profiler|wdt)|css|images|js)/
      security: false
    main:
      anonymous: lazy
      guard:
        authenticators:
          - App\Security\AuthAuthenticator
      logout:
        path: app_logout
        # where to redirect after logout
        # target: app_any_route

      # activate different ways to authenticate
      # https://symfony.com/doc/current/security.html#firewalls-authentication
      # https://symfony.com/doc/current/security/impersonating_user.html
      # switch_user: true

  # Easy way to control access for large sections of your site
  # Note: Only the *first* access control that matches will be used

  role_hierarchy:
    ROLE_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_SUPER_ADMIN]
    ROLE_GESTIONNAIRE: [ROLE_USER, ROLE_ADMIN]

  access_control:
    - { path: ^/admin, roles: [ROLE_ADMIN, ROLE_GESTIONNAIRE] }
    - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/publication, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/publication/new, roles: ROLE_USER }
    - { path: ^/comment, roles: ROLE_USER }
    - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/profile, roles: ROLE_USER }

это часть страницы перенаправления при успехе

      <div id="main">
        <div class="inner">
          <!-- Header -->
          <header id="header">
            <a href="{{ path('home') }}" class="logo">
              <strong>
                {% block pagename %}

                {% endblock %}
              </strong> COMSAS
            </a>
            <ul class="icons">
              {% if app.user %}
                <li><a href="#">{{ app.user.username }}</a></li>
                <li>
                  <a href="/logout">Deconnexion</a>
                </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              {% else %}
                <li>
                  <a href="{{ path('app_login') }}" class="icon fas fa-user">
                    <span class="label">Login</span>
                  </a>
                </li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
              {% endif %}
              <li>
                <a href="#" class="icon brands fa-twitter">
                  <span class="label">Twitter</span>
                </a>
              </li>
              <li>
                <a href="#" class="icon brands fa-facebook-f">
                  <span class="label">Facebook</span>
                </a>
              </li>
              <li>
                <a href="{{ path('publication_index') }}"
                  class="icon fas fa-comments">
                  <span class="label">Forum</span>
                </a>
              </li>
            </ul>
          </header>
          {% block body %}

          {% endblock %}
        </div>
      </div>

      <!-- Sidebar -->
      <div id="sidebar">
        <div class="inner">
          <!-- Search -->
          <section id="search" class="alt">
            <form method="post" action="#">
              <input type="text" name="query" id="query" placeholder="Search" />
            </form>
          </section>

          <!-- Menu -->
          <nav id="menu">
            <header class="major">
              <h2>
                Menu
              </h2>
            </header>
            <ul>
              {% if is_granted('ROLE_ADMIN') %}
                <li><a href="{{ path('admin_home') }}">Espace Admin</a></li>
              {% elseif is_granted('ROLE_GESTIONNAIRE') %}
                <li><a href="{{ path('admin_home') }}">Gestionnaire</a></li>
              {% else %}
                <li><a href="{{ path('publication_index') }}">Forum</a></li>
              {% endif %}
              <li><a href="{{ path('home') }}">Homepage</a></li>
              <li><a href="{{ path('generic') }}">Generic</a></li>
              <li><a href="{{ path('elements') }}">Elements</a></li>

Мне нужна ваша помощь, потому что я не понимаю, почему Сессия по-прежнему пуста, даже если аутентификация прошла успешно.

1 Ответ

0 голосов
/ 30 января 2020

Я полагаю, что проблема заключается в вашей конфигурации access_control.

Способ работы access_control заключается в том, что он останавливается на первой строке, которая соответствует пути, начиная с вершины ACL.

В вашем случае получается, что маршрут не совпадает с ^ / admin, поэтому он переходит на вторую строку и совпадает с ^ / и поэтому считает пользователя анонимным.

Я вижу два изменения, необходимые для исправления:

Во-первых, переместите свой ACL базового пути в последнюю позицию, поскольку он наименее ограничивающий, каждый URL будет соответствовать.

Этот

- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

Во-вторых, когда роль ACL IS_AUTHENTICATED_ANONYMOUSLY, он будет загружать анонимный токен в сеансе пользователя, следовательно, не ожидаемый пользователь.

Окончательный результат для access_control будет:

access_control:
- { path: ^/admin, roles: [ROLE_ADMIN, ROLE_GESTIONNAIRE] }    
- { path: ^/publication, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/publication/new, roles: ROLE_USER }
- { path: ^/comment, roles: ROLE_USER }
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/profile, roles: ROLE_USER }
- { path: ^/, roles: ROLE_USER }

Редактировать: Хорошо, я только что понял, что вы пытаетесь сделать так, чтобы ваша домашняя страница "^ /" была анонимной и аутентифицированной.

Вам также необходимо указать [ROLE_USER, IS_AUTHENTICATED_ANONYMOUSLY] внизу списка ACL.

Теперь с последними внесенными вами изменениями, возможно, вы будете перенаправлены на вход в систему после входа в систему.

Если вы загляните внутрь своего FormLoginAuthenticator на method onAuthenticationSuccess ()

Существует перенаправление с $ targetPath, которое имеет приоритет над домашней страницей.

//If $targetPAth == "/login", you're redirected to login, therefore an anonymous token.
if ( $targetPath = $this->getTargetPath($request->getSession(),$providerKey) )
{
    return new RedirectResponse($targetPath);
}

Возможно, $ targetPath равен "/ login", который IS_AUTHENTICATED_ANONYMOUSLY в вашем ACL. Следовательно, при вводе маршрута "/ login" после входа в систему в сеанс вводится анонимный токен.

Если это не сработает, общий доступ к шаблону ветки формы входа в систему, а также к вашим маршрутам и их URL поможет много.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...