2013-01-14 9 views
7

Sto provando ad implementare il single sign sull'accesso a un sito web usando Symfony2.Login programmaticamente e rimani connesso

L'autenticazione stessa sembra funzionare correttamente, ma solo per la pagina iniziale. Nella pagina successiva che viene caricata l'utente non ha più effettuato l'accesso.

codice rilevante:

$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')); 

Prima pagina (senza il redirect):

Initial page - logged in

Seconda pagina:

Second page - Not logged in anymore

+0

Si sta utilizzando Symfony 2.1? Se è così, prova ad aggiungere le seguenti righe: '$ session-> set ('_ security_'. $ FirewallName, serialize ($ token)); $ session-> save(); ' – Squazic

+0

Ho avuto un problema come questo con un'applicazione web ASP.NET su cui stavo lavorando. Ho svuotato la cache nel mio browser e ha iniziato a funzionare di nuovo. Spero sia facile anche per te :) – Anonymous

+0

@Squazic Sì, sto usando Symfony 2.1. Ho aggiunto lo snippet di sessione, ma sfortunatamente non ha funzionato. –

risposta

6

Solo il codice seguente è necessario per il log-in personalizzato.

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

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

Ciò che fa è impostare UsernamePasswordToken nel contesto di sicurezza. Questo token (e anche l'utente) verrà serializzato e inserito nella sessione. Nella pagina successiva il token non verrà serializzato dalla sessione e l'utente, anche non serializzato, verrà aggiornato.

Il provider di servizi utente in FOSUserBundle effettua questo aggiornamento utilizzando l'ID dell'utente non graduato.

Inoltre, Doctrine2 in alcuni casi utilizza le classi proxy come classi di entità anziché la classe di entità originale. Questa classe proxy sovrascrive la funzione "getId()" dell'entità da un'implementazione complessa complessa con caricamento lento.

Questo insieme potrebbe portare al fatto che, quando si inserisce l'oggetto proxy Doctrine2 in UserPasswordToken, il "getId()" dell'oggetto proxy serializzato e non serializzato non restituirà l'ID originale. Quando ciò accade, l'utente non può essere aggiornato dal fornitore dell'utente e il token diventa non valido.

Una correzione per questo è la creazione di un provider utente personalizzato che sovrascrive "refreshUser()" da un aggiornamento utilizzando il nome utente (o un'altra proprietà univoca).

//... 
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; 
    } 
}