2013-01-14 37 views
7

Tôi đang cố triển khai một dấu hiệu duy nhất khi truy cập vào trang web bằng Symfony2.Đăng nhập theo chương trình và duy trì trạng thái đăng nhập

Bản thân xác thực dường như hoạt động tốt, nhưng chỉ cho trang ban đầu. Trên trang tiếp theo được tải, người dùng không đăng nhập nữa.

đang liên quan:

$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); 
$event = new InteractiveLoginEvent($request, $token); 

$this->get("event_dispatcher")->dispatch(SecurityEvents::INTERACTIVE_LOGIN, $event); 
$this->get("security.context")->setToken($token); 

return $this->redirect($this->generateUrl('sonata_user_profile_show')); 

trang đầu tiên (không chuyển hướng):

Initial page - logged in

trang thứ hai:

Second page - Not logged in anymore

+0

Bạn đang sử dụng Symfony 2.1? Nếu vậy, hãy thử thêm các dòng sau: '$ session-> set ('_ security_'. $ FirewallName, serialize ($ token)); $ session-> save(); ' – Squazic

+0

Tôi gặp sự cố như thế này với ứng dụng web ASP.NET mà tôi đang thực hiện. Tôi đã xóa bộ nhớ cache trong trình duyệt của mình và nó bắt đầu hoạt động trở lại. Hy vọng rằng nó cũng dễ dàng cho bạn :) – Anonymous

+0

@Squazic Vâng, tôi đang sử dụng Symfony 2.1. Tôi đã thêm đoạn mã phiên, nhưng tiếc là đoạn mã không hoạt động. –

Trả lời

6

Chỉ cần có mã sau để đăng nhập tùy chỉnh.

$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); 
$this->get("security.context")->setToken($token); 

return $this->redirect($this->generateUrl('sonata_user_profile_show')); 

Điều này có nghĩa là đặt Tên người dùngPasswordTrong ngữ cảnh bảo mật. Mã thông báo này (và cả người dùng) sẽ được tuần tự hóa và đưa vào phiên làm việc. Trên trang tiếp theo mã thông báo sẽ được unserialized từ phiên và, cũng unserialized, người dùng sẽ được làm mới.

Nhà cung cấp người dùng trong FOSUserBundle thực hiện việc làm mới này bằng cách sử dụng id của người dùng chưa được thực hiện.

Ngoài ra, Doctrine2 trong một số trường hợp sử dụng lớp proxy làm lớp thực thể thay vì lớp thực thể gốc. Lớp proxy này sẽ ghi đè hàm "getId()" của thực thể bằng cách triển khai phức tạp tải lười biếng phức tạp. Điều này cùng nhau có thể dẫn đến thực tế rằng, khi bạn đặt đối tượng proxy Doctrine2 trong UserPasswordToken, "getId()" của đối tượng proxy được tuần tự hóa và sau đó unserialized sẽ không trả lại id ban đầu. Khi điều đó xảy ra, người dùng không thể được làm mới bởi nhà cung cấp người dùng và mã thông báo sẽ không hợp lệ.

Khắc phục sự cố này là tạo nhà cung cấp người dùng tùy chỉnh ghi đè "refreshUser()" bằng cách làm mới bằng tên người dùng (hoặc thuộc tính duy nhất khác).

//... 
class UserProvider extends FOSUserProvider 
{ 
    /** 
    * {@inheritDoc} 
    */ 
    public function refreshUser(SecurityUserInterface $user) 
    { 
     if (!$user instanceof User) { 
      throw new UnsupportedUserException(sprintf('Expected an instance of User, but got "%s".', get_class($user))); 
     } 

     if (null === $reloadedUser = $this->userManager->findUserBy(array('username' => $user->getUsername()))) { 
      throw new UsernameNotFoundException(sprintf('User with username "%s" could not be reloaded.', $user->getUsername())); 
     } 

     return $reloadedUser; 
    } 
} 
Các vấn đề liên quan