2012-05-02 31 views
12

Tôi đang làm việc trên ứng dụng Symfony 2 nơi người dùng phải chọn một cấu hình trong quá trình đăng nhập.Kiểm tra xác thực thủ công Symfony 2

Người dùng có thể có hồ sơ nhiều người để làm việc cùng và họ chỉ biết tiểu sử của riêng họ. Vì vậy, trước tiên, tôi cần phải nhắc cho tên người dùng và mật khẩu, nếu những người đó là chính xác, tôi không nên đăng nhập người dùng, tôi cần nhắc nhở cho người dùng phù thủy hồ sơ sẽ sử dụng trong phiên.

Vì vậy, tôi hiển thị biểu mẫu có trường tên người dùng và mật khẩu và gửi biểu mẫu bằng yêu cầu Ajax, yêu cầu đó phản hồi với danh sách hồ sơ nếu tên người dùng và mật khẩu chính xác hoặc mã lỗi. Cuối cùng người dùng đăng nhập vào hệ thống bằng tên người dùng, mật khẩu và hồ sơ.

Vấn đề là tôi không biết cách kiểm tra xem dữ liệu xác thực có đúng không (sử dụng tất cả các trình quản lý xác thực, nhà cung cấp người dùng, v.v.) để thực hiện bước trung gian này (nhắc cho hồ sơ) mà không thực sự đăng nhập người dùng.

Có ai có thể giúp tôi với điều này không?

Trả lời

2

tôi đã sử dụng mã từ @Jordon@Potor Polak để quấn logic trong một dịch vụ độc lập sử dụng các thẻ truy cập hiện tại để xác nhận mật khẩu. Có lẽ một số nhu cầu này:

services.yml:

app.validator.manual_password: 
    class: AppBundle\Service\ManualPasswordValidator 
    arguments: 
     - '@security.token_storage' 
     - '@security.encoder_factory' 

ManualPasswordValidator.php:

<?php 

namespace AppBundle\Service; 

use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; 
use Symfony\Component\Security\Core\Encoder\EncoderFactory; 

/** 
* Class ManualPasswordValidator 
* 
* @package AppBundle\Service 
*/ 
class ManualPasswordValidator 
{ 
    /** 
    * @var EncoderFactory 
    */ 
    protected $encoderFactory; 

    /** 
    * @var TokenStorage 
    */ 
    protected $tokenStorage; 

    /** 
    * ManualPasswordValidator constructor. 
    * 
    * @param EncoderFactory $encoderFactory 
    * @param TokenStorage $tokenStorage 
    */ 
    public function __construct(TokenStorage $tokenStorage, EncoderFactory $encoderFactory) 
    { 
     $this->encoderFactory = $encoderFactory; 
     $this->tokenStorage = $tokenStorage; 
    } 

    /** 
    * @param $password 
    * @return bool 
    */ 
    public function passwordIsValidForCurrentUser($password) 
    { 
     $token = $this->tokenStorage->getToken(); 

     if ($token) { 
      $user = $token->getUser(); 

      if ($user) { 
       $encoder = $this->encoderFactory->getEncoder($user); 

       if ($encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { 
        return true; 
       } 
      } 
     } 

     return false; 
    } 
} 

Sau này bạn có thể tiêm các ManualPasswordValidator bất cứ nơi nào bạn muốn và sử dụng nó như:

$password  = $request->get('password'); 
$passwordIsValid = $this->manualPasswordValidator->passwordIsValidForCurrentUser($password); 
16

Bạn có thể làm một cái gì đó như thế này để lấy người sử dụng và tự kiểm tra mật khẩu -

$username = trim($this->getRequest()->query->get('username')); 
$password = trim($this->getRequest()->query->get('password')); 

$em = $this->get('doctrine')->getEntityManager(); 
$query = $em->createQuery("SELECT u FROM \Some\Bundle\Entity\User u WHERE u.username = :username"); 
$query->setParameter('username', $username); 
$user = $query->getOneOrNullResult(); 

if ($user) { 
    // Get the encoder for the users password 
    $encoder_service = $this->get('security.encoder_factory'); 
    $encoder = $encoder_service->getEncoder($user); 
    $encoded_pass = $encoder->encodePassword($password, $user->getSalt()); 

    if ($user->getPassword() == $encoded_pass) { 
    // Get profile list 
    } else { 
    // Password bad 
    } 
} else { 
    // Username bad 
} 

Một khi bạn đã có hồ sơ của bạn trở lại từ khách hàng, bạn có thể thực hiện việc đăng nhập bằng tay trong bộ điều khiển máy chủ AJAX dễ dàng đủ quá -

// Get the security firewall name, login 
$providerKey = $this->container->getParameter('fos_user.firewall_name'); 
$token = new UsernamePasswordToken($user, $password, $providerKey, $user->getRoles()); 
$this->get("security.context")->setToken($token); 

// Fire the login event 
$event = new InteractiveLoginEvent($this->getRequest(), $token); 
$this->get("event_dispatcher")->dispatch("security.interactive_login", $event); 

có thể cần một vài dòng sử dụng -

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; 
use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; 
+1

tôi mạnh mẽ khuyên bạn nên xem giải pháp @Piotr Polak vì nó hoạt động với l bộ mã hóa mật khẩu. –

+0

Không chỉnh sửa câu trả lời để thay đổi câu trả lời hoàn toàn. Thay vào đó, upvote câu trả lời đúng. – Alsciende

1

Cách duy nhất tôi có thể xác thực người dùng của tôi trên một bộ điều khiển là tạo một yêu cầu con và sau đó chuyển hướng. Dưới đây là mã của tôi, tôi đang sử dụng silex nhưng bạn có thể dễ dàng thích nghi với nó để symfony2:

$subRequest = Request::create($app['url_generator']->generate('login_check'), 'POST', array('_username' => $email, '_password' => $password, $request->cookies->all(), array(), $request->server->all()); 

$response = $app->handle($subRequest, HttpKernelInterface::MASTER_REQUEST, false); 

return $app->redirect($app['url_generator']->generate('curriculos.editar')); 
30

Một vấn đề với @ đang Jordon là nó sẽ không làm việc với các thuật toán băm tạo ra băm khác nhau cho cùng một mật khẩu (chẳng hạn như bcrypt rằng câu chuyện nội bộ các thông số của nó, cả số lần lặp lại và muối). Chính xác hơn là sử dụng isPasswordValid của Bộ mã hóa để so sánh mật khẩu.

Đây là mã được cải thiện hoạt động tốt với bcrypt:

$username = trim($this->getRequest()->query->get('username')); 
$password = trim($this->getRequest()->query->get('password')); 

$em = $this->get('doctrine')->getManager(); 
$query = $em->createQuery("SELECT u FROM \Some\Bundle\Entity\User u WHERE u.username = :username"); 
$query->setParameter('username', $username); 
$user = $query->getOneOrNullResult(); 

if ($user) { 
    // Get the encoder for the users password 
    $encoder_service = $this->get('security.encoder_factory'); 
    $encoder = $encoder_service->getEncoder($user); 

    // Note the difference 
    if ($encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt())) { 
    // Get profile list 
    } else { 
    // Password bad 
    } 
} else { 
    // Username bad 
} 
Các vấn đề liên quan