已按照以下说明进行操作:https://symfony.com/doc/current/security/form_login_setup.html,并在第3步(在onAuthenticationSuccess
方法中)-如果我将Exception保留在外,探查器栏将显示用户登录,但是如果我注释在重定向中,用户将在下一页上丢失。会话已建立并作为pdo工作。
有人有什么想法吗?
LoginFormAuthenticator.php
<?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\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\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
}
public function supports(Request $request)
{
return 'app_login' === $request->attributes->get('_route')
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
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(['email' => $credentials['email']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
// Check the user's password or other credentials and return true or false
// If there are no credentials to check, you can just return true
return true;
//throw new \Exception('TODO: check the credentials inside '.__FILE__);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
//throw new \Exception('TODO: provide a valid redirect inside '.__FILE__);
return new RedirectResponse($this->urlGenerator->generate('app_dashboard'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}
DashboardController.php
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class DashboardController extends AbstractController
{
private $session;
function __construct(SessionInterface $session)
{
$this->session = $session;
}
/**
* @Route("/dashboard", name="app_dashboard")
*/
function dashboard()
{
return $this->render('account/dashboard.html.twig', []);
}
}
security.yaml
security:
providers:
users:
entity:
class: 'App\Entity\User'
property: 'email'
encoders:
App\Entity\User:
algorithm: 'auto'
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
guard:
authenticators:
- App\Security\LoginFormAuthenticator
logout:
path: app_logout
access_control:
- { path: ^/dashboard, roles: ROLE_USER }
User.php
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* User
*
* @ORM\Table(name="user")
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class User implements UserInterface, \Serializable
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="email", type="string", length=2048, nullable=true)
*/
private $email;
/**
* @var string
*
* @ORM\Column(name="password", type="string", length=4096, nullable=false)
*/
private $password;
/**
* @var string
*
* @ORM\Column(name="salt", type="string", length=2048, nullable=true)
*/
private $salt;
////////
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getSalt(): ?string
{
return $this->salt;
}
public function setSalt(string $salt): self
{
$this->salt = $salt;
return $this;
}
/**
* @inheritDoc
*/
public function getUsername()
{
return $this->email;
}
/**
* @inheritDoc
*/
public function getRoles()
{
return array('ROLE_USER');
}
/**
* @inheritDoc
*/
public function eraseCredentials()
{
}
/**
* @inheritDoc
*/
public function equals(UserInterface $user)
{
return $this->id === $user->getId();
}
/**
* @see \Serializable::serialize()
*/
public function serialize()
{
return serialize(array(
$this->id,
));
}
/**
* @see \Serializable::unserialize()
*/
public function unserialize($serialized)
{
list (
$this->id,
) = unserialize($serialized);
}
public function isEqualTo(UserInterface $user)
{
if (!$user instanceof User) {
return false;
}
if ($this->password !== $user->getPassword()) {
return false;
}
if ($this->salt !== $user->getSalt()) {
return false;
}
if ($this->email !== $user->getEmail()) {
return false;
}
return true;
}
}
编辑.. 当注释异常时,日志显示:
INFO
19:32:37
request Matched route "app_login".
Show context
INFO
19:32:38
security Guard authentication successful!
Show context
CRITICAL
19:32:38
request Uncaught PHP Exception Exception: "TODO: provide a valid redirect inside /var/www/src/Security/LoginFormAuthenticator.php" at /var/www/src/Security/LoginFormAuthenticator.php line 87
当重定向存在时,日志说:
19:30:24
security Checking for guard authentication credentials.
Hide context
[▼
"firewall_key" => "main"
"authenticators" => 1
]
19:30:24
security Checking support on guard authenticator.
Hide context
[▼
"firewall_key" => "main"
"authenticator" => "App\Security\LoginFormAuthenticator"
]
19:30:24
security Guard authenticator does not support the request.
Hide context
[▼
"firewall_key" => "main"
"authenticator" => "App\Security\LoginFormAuthenticator"
]
.. edit-http和https中的行为相同。
答案 0 :(得分:0)
我想为您发表评论,但我的声誉不到50分,所以我将在评论中写下评论。
不建议使用支持方法。 不再使用它。
使用以下示例:
LoginFormAuthenticator.php
public function getCredentials(Request $request)
{
$isLoginSubmit = 'user_login' === $request->attributes->get('_route') && $request->isMethod('POST');
if(!$isLoginSubmit) {
return;
}
//...other codes
}
protected function getDefaultSuccessRedirectUrl()
{
return $this->urlGenerator->generate('user_dashboard');
}
UserController.php
<?php
namespace AppBundle\Controller\User;
use AppBundle\Form\User\UserManager\UserLoginForm;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\Routing\Annotation\Route;
/**
* User controller.
*
* @Route("User")
*/
class UserController extends Controller
{
/**
* @Route("/login", name="user_login")
*/
public function loginAction()
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
$form = $this->createForm(UserLoginForm::class, ["_username" => $lastUsername]);
return $this->render('User/login.html.twig', [
'form' => $form->createView(),
'error' => $error,
]);
}
/**
* @Route("/logout", name="user_logout")
*/
public function logoutAction()
{
throw new \Exception('User logout');
}
/**
* @Route("/dashboard", name="user_dashboard")
*/
public function dashboardAction()
{
return $this->render('User/dashboard.html.twig');
}
}
security.yaml
需要提供者和模式:
firewalls:
//...other firewalls
main:
anonymous: ~
pattern: ^/user
provider: users
access_control:
- { path: ^/user/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/user, roles: ROLE_USER }
希望能为您提供帮助。
留下任何反馈意见。
答案 1 :(得分:0)
问题是没有刷新用户,Guard Authenticator确实在做应有的事情。将用户实体还原到以下固定的实体。
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @UniqueEntity(fields={"email"}, message="There is already an account with this email")
*/
class User implements UserInterface
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="string", length=255, unique=true)
*/
private $email;
/**
* @ORM\Column(type="string", length=255)
*/
private $password;
/**
* @ORM\Column(type="string", length=255)
*/
private $name;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getUsername()
{
return $this->email;
}
public function getPassword(): ?string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): self
{
$this->name = $name;
return $this;
}
////
public function getRoles()
{
return [
'ROLE_USER'
];
}
public function getSalt()
{
}
public function eraseCredentials()
{
}
}