Symfony 3 bcrypt密码无法验证

时间:2017-07-05 08:54:10

标签: php symfony authentication login bcrypt

我很可能错过了一些愚蠢的东西,但我花了很多时间在这上面,所以感谢任何帮助。

身份验证基于this tutorial

我使用bcrypt对密码进行编码,似乎在用户注册时工作正常。

但即使输入的密码正确无误,登录时也会抛出错误:

  

凭据无效。

我确认电子邮件和密码正确到达登录验证器(登录表单是通过Ajax提交的)。

此外,getUser()方法似乎正在从db中检索$ user对象和相应的密码。

security.yml设置如下:

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())
        );           
    }
}
}

登录表单身份验证器(设置为服务):

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)摘录按要求

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)的摘录

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)

1 个答案:

答案 0 :(得分:0)

在Edwin让我朝着正确的方向前进之后,我设法让它发挥作用。实际上,加密并不是唯一的问题。 这些更改主要涉及注册控制器,其中修改了密码加密的代码。 我还更改了表单身份验证器,现在基于this

因为我的问题上显示的先前基数已过时。

最后,Symfony与Ajax并不是很多朋友,因此Ajax URL适用于开发环境。

以下是整个代码:

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 url在开发时的样子:]

            $.ajax({
            url: "/app_dev.php/login_check",
            type: "POST",
            dataType: "json",
            data: str,
            success: function(data) {
    .....