问题描述
很可能我错过了一些愚蠢的东西,但是我花了很多时间在此上,因此我们将不胜感激.
Most likely I am missing some silly stuff, but I spent quite some time on this, so any help is appreciated.
身份验证基于本教程
我正在使用bcrypt对密码进行编码,看来在用户注册时工作正常.
I am using bcrypt to encode the password and it seems that is working properly on user signup.
但是登录时,即使输入的密码正确,也会在下面引发错误:
But when logging in it throws error below, even though the password entered is correct:
我验证了电子邮件和密码是否正确到达了登录身份验证器(登录表单是通过Ajax提交的).
I verified that the email and password arrive properly at the login authenticator ( login form is submitted via Ajax ).
此外,getUser()方法似乎正在执行其工作,它从数据库中检索$ user对象和相应的密码.
Also the getUser() method seems to be doing its job of retrieving $user object and the corresponding password from the db.
security.yml设置如下:
The security.yml is set as follows:
security:
encoders:
UsedBundle\Entity\User:
algorithm: bcrypt
这是注册控制者:
namespace UsedBundle\Controller;
use UsedBundle\Form\UserType;
use UsedBundle\Entity\User;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use UsedBundle\Service\sendEmail;
class RegistrationController extends Controller
{
/**
* @Route("/inscription", name="inscription")
*/
public function registerAction(Request $request)
{
$user = new User();
$form = $this->createForm(UserType::class, $user);
if ($request->isMethod('POST')) {
$form->submit($request->request->get($form->getName('user')));
if(!$form->isValid()){
// handle invalid form
}
if ($form->isSubmitted() && $form->isValid()) {
$password = $this->get('security.password_encoder')
->encodePassword($user, $user->getPlainPassword());
$user->setPassword($password);
$user->setUserKey( $user->getEmail() );
$user->setUserKeyTime();
$user->setDateReg();
$em = $this->getDoctrine()->getManager('used');
$em->persist($user);
$em->flush();
return new JsonResponse(array(
'status' => 'ok',
'message' => 'Success!')
);
}
}else{
return $this->render(
'common/register.html.twig',
array('form' => $form->createView())
);
}
}
}
登录表单身份验证器(设置为服务):
The login form authenticator ( setup as a service ):
namespace UsedBundle\Security;
use Symfony\Component\Security\Guard\Authenticator\AbstractFormLoginAuthenticator;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\Security;
use UsedBundle\Entity\User;
use UsedBundle\Repository\UserRepository;
use Symfony\Component\Security\Core\Exception\BadCredentialsException;
class FormLoginAuthenticator extends AbstractFormLoginAuthenticator
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getCredentials(Request $request)
{
if ($request->getPathInfo() != '/login_check') {
return;
}
$username = $request->request->get('_email');
$request->getSession()->set(Security::LAST_USERNAME, $username);
$password = $request->request->get('_password');
return array(
'username' => $username,
'password' => $password
);
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$username = $credentials['username'];
$user = $this->container
->get('doctrine')
->getRepository('UsedBundle:User', 'used')
->findOneByemail( $username );
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
$plainPassword = $credentials['password'];
$encoder = $this->container->get('security.password_encoder');
if (!$encoder->isPasswordValid($user, $plainPassword)){
throw new BadCredentialsException();
}else{
$this->pass_error = 'no error';
}
}
protected function getLoginUrl()
{
return $this->container->get('router')
->generate('homepage');
}
protected function getDefaultSuccessRedirectUrl()
{
return $this->container->get('router')
->generate('homepage');
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
// AJAX! Return some JSON
if ($request->isXmlHttpRequest()) {
return new JsonResponse(
array('userId' => $token->getUser()->getId(),
'statut' => 'ok'
)
);
}
// for non-AJAX requests, return the normal redirect
return parent::onAuthenticationSuccess($request, $token, $providerKey);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
return new JsonResponse(
array('message' => $exception->getMessageKey(),
'statut' => 'error',
'passerror' => $this->pass_error )
);
}
根据要求在checkCredentials()上摘录var_dump($ user)
Excerpt of var_dump($user) on checkCredentials() as requested
object(UsedBundle\Entity\User)#329 (15) {
["id":"UsedBundle\Entity\User":private]=>
int(7)
["avatar":"UsedBundle\Entity\User":private]=>
string(11) "dsfdfafadfa"
["name":"UsedBundle\Entity\User":private]=>
string(9) "dfdffadfa"
["password":"UsedBundle\Entity\User":private]=>
string(64) "jjuewij/sc9Af17i+ZXAUcrdiZX83HHMLjTNVSnJ34qGCp6BAxisVtjiG3Nm+uH5"
["plainPassword":"UsedBundle\Entity\User":private]=>
NULL
["email":"UsedBundle\Entity\User":private]=>
string(22) "myemail@gmail.com"
["phone":"UsedBundle\Entity\User":private]=>
string(12) "445454545454"
["roles":"UsedBundle\Entity\User":private]=>
string(9) "ROLE_USER"
["isActive":"UsedBundle\Entity\User":private]=>
bool(true)
根据要求,onAuthenticationFailure()上的var_dump($ exception)摘录
as requested, excerpts of var_dump($exception) on onAuthenticationFailure()
object(Symfony\Component\Security\Core\Exception\BadCredentialsException)#322 (8) {
["token":"Symfony\Component\Security\Core\Exception\AuthenticationException":private]=>
object(Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken)#61 (6) {
["credentials":"Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken":private]=>
array(2) {
["username"]=>
string(22) "myemail@gmail.com"
["password"]=>
string(8) "senha444"
}
["guardProviderKey":"Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken":private]=>
string(6) "main_0"
["user":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=>
NULL
["roles":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=>
array(0) {
}
["authenticated":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=>
bool(false)
["attributes":"Symfony\Component\Security\Core\Authentication\Token\AbstractToken":private]=>
array(0) {
}
}
["message":protected]=>
string(0) ""
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(78) "/Users/BAMAC/Sites/Symfony1/src/UsedBundle/Security /FormLoginAuthenticator.php"
["line":protected]=>
int(58)
推荐答案
在Edwin将我引导到正确的方向之后,我设法使它起作用.实际上,加密不是唯一的问题.所做的更改主要涉及注册控制器,在该控制器中修改了密码加密代码.我还更改了表单身份验证器,该身份验证器现在基于此
After Edwin put me in the right direction, I managed to get this to work. In reality the encryption was not the only issue.The changes concern mainly the registration controller, where the code for password encryption was modified.I also changed the form authenticator which is now based upon this
我的问题之前指出的基础已经过时.
as the previous base indicated on my question is outdated.
最后,Symfony与Ajax并不是很多朋友,因此Ajax URL被改编为可用于开发环境.
Finally, Symfony are not very much friends with Ajax, so the Ajax URL was adapted to work for dev environment.
这是整个代码:
security.yml
security.yml
security:
encoders:
UsedBundle\Entity\User:
algorithm: bcrypt
providers:
db_provider:
entity:
class: UsedBundle:User
property: email
manager_name: used
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: ~
provider: db_provider
form_login:
login_path: /
username_parameter: _email
check_path: /login_check
guard:
authenticators:
- app.form_login_authenticator
logout:
path: /logout
target: /
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
更改注册控制器:
if ($form->isSubmitted() && $form->isValid()) {
$this->formData = $request->request->get($form->getName('user'));
$this->plainPassword = $this->formData['plainPassword']['first'];
$password = $this->get('security.password_encoder')
->encodePassword($user, $this->plainPassword );
.....
新的身份验证器:
namespace UsedBundle\Security;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Guard\AbstractGuardAuthenticator;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Exception\AuthenticationException;
use Symfony\Component\Security\Core\User\UserProviderInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\Security\Core\Security;
class FormLoginAuthenticator extends AbstractGuardAuthenticator
{
private $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
public function getCredentials(Request $request)
{
if ($request->getPathInfo() != '/login_check') {
return;
}
$email = $request->request->get('_email');
$request->getSession()->set(Security::LAST_USERNAME, $email);
$password = $request->request->get('_password');
return array(
'email' => $email,
'password' => $password
);
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$email = $credentials['email'];
return $this->user = $this->container
->get('doctrine')
->getRepository('UsedBundle:User', 'used')
->findOneByemail( $email );
}
public function checkCredentials($credentials, UserInterface $user)
{
$plainPassword = $credentials['password'];
$encoder = $this->container->get('security.password_encoder');
if (!$encoder->isPasswordValid($user, $plainPassword)){
throw new BadCredentialsException();
}else{
return true;
}
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
$session=$request->getSession();
$session->set('seller_id', $token->getUser()->getId());
$session->set('email', $token->getUser()->getEmail());
return new JsonResponse(
array(
'userId' => $token->getUser()->getId(),
'message' => $this->credentials,
'statut' => 'ok',
'roles' => $token->getUser()->getRoles(),
'email' => $token->getUser()->getEmail(),
)
);
// for non-AJAX requests, return the normal redirect
//return parent::onAuthenticationSuccess($request, $token, $providerKey);
}
public function onAuthenticationFailure(Request $request, AuthenticationException $exception)
{
$data = array(
'message' => strtr($exception->getMessageKey(), $exception->getMessageData())
// or to translate this message
// $this->translator->trans($exception->getMessageKey(), $exception->getMessageData())
);
return new JsonResponse($data, Response::HTTP_FORBIDDEN);
}
/**
* Called when authentication is needed, but it's not sent
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$data = array(
'message' => 'Authentication Required'
);
return new JsonResponse($data, Response::HTTP_UNAUTHORIZED);
}
public function supportsRememberMe()
{
return false;
}
}
登录控制器:
namespace UsedBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class LoginController extends Controller
{
/**
* @Route("/login", name="login")
*/
public function loginAction(Request $request)
{
$helper = $this->get('security.authentication_utils');
return $this->render('common/login.html.twig', array(
// last username entered by the user (if any)
'last_username' => $helper->getLastUsername(),
// last authentication error (if any)
'error' => $helper->getLastAuthenticationError(),
));
}
/**
* @Route("/login_check", name="security_login_check")
*/
public function loginCheckAction()
{
// will never be executed
}
}
这就是在开发中使用Ajax网址的样子:]
And this is how the Ajax url should look like while in dev:]
$.ajax({
url: "/app_dev.php/login_check",
type: "POST",
dataType: "json",
data: str,
success: function(data) {
.....
这篇关于Symfony 3 bcrypt密码无法验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!