symfony上的凭据无效

  • 本文关键字:无效 symfony symfony
  • 更新时间 :
  • 英文 :


各位晚上好,我几天来一直在处理这个问题,无论我做了什么改变,它都会一直存在。。基本上在登录时,当我放一封无效的电子邮件时,它会说找不到电子邮件,当我输入无效密码时,它说错误的密码(我当然编辑了它(,但当它们都正确时,它显示出于某种原因的无效凭据,我真的很不同。。请帮我,我可以链接任何页面代码,但我90%确信代码是正确的,提前感谢

SecurityController.php

<?php
namespace AppController;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('/index');
}
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
throw new LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}

security.yaml

security:
encoders:

AppEntityUser5:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:

app_user_provider:
entity:
class: 'AppEntityUser5'
property: 'email'




firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
provider: app_user_provider
form_login: 
login_path: app_login
check_path: app_login
guard:
authenticators:
- AppSecurityLoginFormAuthenticator

entry_point: AppSecurityLoginFormAuthenticator
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

# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# 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
#access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
# - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }

登录.html.wig

{% extends 'home.html.twig' %}
{% block title %}Log in!{% endblock %}
{% block body %}
<form method="post" action="{{ path('app_login')}}">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
{% if app.user %}
<div class="mb-3">
You are logged in as {{ app.user.username }}, <a href="{{ path('app_logout') }}">Logout</a>
</div>
{% endif %}
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail">Email</label>
<input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" required autofocus>
<label for="inputPassword">Password</label>
<input type="password" name="password" id="inputPassword" class="form-control" required>
<input type="hidden" name="_csrf_token"
value="{{ csrf_token('authenticate') }}"
>
{#
Uncomment this section and add a remember_me option below your firewall to activate remember me functionality.
See https://symfony.com/doc/current/security/remember_me.html
<div class="checkbox mb-3">
<label>
<input type="checkbox" name="_remember_me"> Remember me
</label>
</div>
#}
<button class="btn btn-lg btn-primary" type="submit" >
Sign in
</button>
</form>
{% endblock %}

登录FormAuthenticator

<?php
namespace AppSecurity;
use AppEntityUser5;
use DoctrineORMEntityManagerInterface;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingGeneratorUrlGeneratorInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;
use SymfonyComponentSecurityCoreExceptionCustomUserMessageAuthenticationException;
use SymfonyComponentSecurityCoreExceptionInvalidCsrfTokenException;
use SymfonyComponentSecurityCoreSecurity;
use SymfonyComponentSecurityCoreUserUserInterface;
use SymfonyComponentSecurityCoreUserUserProviderInterface;
use SymfonyComponentSecurityCsrfCsrfToken;
use SymfonyComponentSecurityCsrfCsrfTokenManagerInterface;
use SymfonyComponentSecurityGuardAuthenticatorAbstractFormLoginAuthenticator;
use SymfonyComponentSecurityGuardPasswordAuthenticatedInterface;
use SymfonyComponentSecurityHttpUtilTargetPathTrait;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator implements PasswordAuthenticatedInterface
{
use TargetPathTrait;
private const LOGIN_ROUTE = 'app_login';
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 self::LOGIN_ROUTE === $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(User5::class)->findOneBy(['email' => $credentials['email']]);


if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
$user = $this->entityManager->getRepository(User5::class)->findOneBy(['password' => $credentials['password']]);

if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Wrong password.');
}

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);
}
// For example : return new RedirectResponse($this->urlGenerator->generate('some_route'));
return new RedirectResponse($this->urlGenerator->generate('index'));

throw new Exception('TODO: provide a valid redirect inside '.__FILE__);
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}

User5.php

<?php
namespace AppEntity;
use DoctrineORMMapping as ORM;
use SymfonyComponentSecurityCoreUserUserInterface;
use DoctrineCommonCollectionsCollection;
use DoctrineCommonCollectionsArrayCollection;
use DoctrineComponentValidatorConstraints as Assert;
use SymfonyBridgeDoctrineValidatorConstraintsUniqueEntity;
/**
* @ORMEntity()
* @UniqueEntity("email")
*/
/**
* @ORMEntity(repositoryClass="AppRepositoryUser5Repository")
* @UniqueEntity(
* fields={"email"},
* message="That Email is already taken , try another "
* )
*/
class User5 implements UserInterface
{
/**
* @ORMId()
* @ORMGeneratedValue()
* @ORMColumn(type="integer")
*/
private $id;
/**
* @ORMColumn(unique=true, type="string", nullable=false)
*/
private $email;
/**
* @ORMColumn(type="json")
*/
private $roles = [];
/**
* @var string The hashed password
* @ORMColumn(type="string")
*/
private $password;
/**
* @ORMManyToMany(targetEntity="AppEntityRole", mappedBy="Users")
*/
private $userRoles;
public function __construct()
{
$this->userRoles = new ArrayCollection();
}
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;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUsername(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* @see UserInterface
*/
public function getPassword(): string
{
return (string) $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function getSalt()
{
// not needed when using the "bcrypt" algorithm in security.yaml
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
/**
* @return Collection|Role[]
*/
public function getUserRoles(): Collection
{
return $this->userRoles;
}
public function addUserRole(Role $userRole): self
{
if (!$this->userRoles->contains($userRole)) {
$this->userRoles[] = $userRole;
$userRole->addUser($this);
}
return $this;
}
public function removeUserRole(Role $userRole): self
{
if ($this->userRoles->contains($userRole)) {
$this->userRoles->removeElement($userRole);
$userRole->removeUser($this);
}
return $this;
}

}

你应该删除这几行,密码在数据库中是加密的,所以你不能用他的密码检索用户,Symfony会做这项工作(比较两个密码(。

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

if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Wrong password.');
}

我自己解决了这个问题,显然你不能同时使用guard和form登录,你必须选择其中一个,因为两者都做同样的工作,一个很容易,另一个是自定义的。我忘记了注册功能中的一些非常重要的东西,忘记了编码密码,现在它工作得很好

这是新的寄存器函数

public function register(Request $request , EntityManagerInterface $entityManager, UserPasswordEncoderInterface $encoder)
{
$user = new User5();

$form = $this->createForm(Form::class, $user);

$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$hashed = $encoder->encodePassword($user, $user->getPassword());
$user->setPassword($hashed); 

$entityManager->persist($user);
$entityManager->flush();
$this->addFlash("success", "Welcome to our application");
return $this->redirectToRoute("app_login");  

}



return $this->render('account/registration.html.twig',[
'form' => $form->createView()
]);


}

新的安全性。yaml

security:
encoders:
AppEntityUser5:
algorithm: bcrypt
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:

app_user_provider:
entity:
class: 'AppEntityUser5'
property: 'email'

firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
provider: app_user_provider
form_login: 
login_path: app_login
check_path: app_login
# default_target_path: dashboard

logout:
path: logout_user
target: index
# target: app_any_route




# activate different ways to authenticate

# https://symfony.com/doc/current/security.html#firewalls-authentication

# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# 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
#access_control:
# - { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
# - { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
# - { path: ^/api,       roles: IS_AUTHENTICATED_FULLY }

最新更新