Commits

christiansalazar committed eb37d04

FIXED ISSUE #61 - allowAutoLogin enabled. cookie+session duration.

Comments (1)

  1. Christian Salazar repo owner

    Capacidad de allowAutoLogin Habilitada

    Este commit trae consigo la capacidad de allowAutoLogin. Para habilitar el autoLogin debe configurarse en config/main el atributo 'allowAutoLogin'=>true para el componente 'user'.

    Cómo funciona.

    1. Cuando un usuario hace login (hace POST) se guarda en memoria de cookies el ID del CrugeStoredUser ademas de otra informacion.
      https://bitbucket.org/christiansalazarh/cruge/src/eb37d04ec6d5/components/CrugeWebUser.php?at=master#cl-381

    2. El usuario iniciara sesion, y sus credenciales habran sido guardadas. Cuando CIERRE EL BROWSER y lo vuelva a abrir verá que sus credenciales estan guardadas (aunque no salgan en el form), notandose que la aplicacion INICIA SESION automaticamente.
      No confundir: "guardado del campo del form", con: "guardado del ID del usuario en cookies", ni confundir con: "DURACION DE SESION de Cruge", son tres cosas distintas

    3. Cuando el usuario vuelve a abrir el browser dentro del tiempo de sesion indicado en "Variables del Sistema" de Cruge notará que la sesion se auto-inicia pero esta "no pasara por el filtro de sesion de Cruge", debido a que generara problemas porque se pretenderan usar objetos que aun no han sido cargados por YII. Se hae una llamada a parent::init() (de CWebUser) dentro de CrugeWebUser::init(), para que sea la clase base CWebUser quien invoque a restoreFromCookies (https://github.com/yiisoft/yii/blob/master/framework/web/auth/CWebUser.php#L195), a la cual se le ha hecho un override en CrugeWebUser para que haga lo que se necesita en este caso particular de cruge: https://bitbucket.org/christiansalazarh/cruge/src/eb37d04ec6d5/components/CrugeWebUser.php?at=master#cl-264

    4. Lo que se hace en CrugeWebUser::restoreFromCookies() es casi lo mismo que Yii original, con la salvedad de tomar el ID del usuario y buscar su ultima sesion de Cruge, para pasarsela a CrugeWebUser::setSessionId() y de esa forma LISTO ! cruge ha iniciado sesion.

    Consideraciones Importantes:

    La duracion de la cookie se ha establecido IGUAL que la duracion de la Sesion de Cruge, para evitar problemas, recordando que si la duracion de la cookie es menor a la de la sesion entonces la sesion caducara mientras que las credenciales estaran vigentes confundiendo al usuario y al programador. Podria darse el caso en que las credenciales duren 1 año...pero la sesion de cruge dure 5 minutos...pero es confuso para el usuario, aunque se podria hacer alterando el valor "de duracion de cookie" que se le da a CrugeWebUser::login() aqui: https://bitbucket.org/christiansalazarh/cruge/src/eb37d04ec6d53e37c3b800bfe3fb2682d46f2fd5/models/ui/CrugeLogon.php?at=master#cl-109

Files changed (2)

components/CrugeWebUser.php

         return "";
     }
 
+	protected function restoreFromCookie()
+	{
+		// invocada cuando allowAutoLogin es true.
+
+		// 1. Cuando se invoca a login() y allowAutoLogin es true y
+		// ($duration > 0), se invoca a saveToCookie guardando
+		// alli el ID del usuario.
+		
+		// 2. Se recuperara el ID del usuario, luego
+		// se buscara el objeto CrugeSession que tenga asignado,
+		// el mas nuevo, y se revalida a ver si no ha caducado,
+		// para finalmente reasignarlo a la autenticacion.
+		
+		// 3. Si la sesion del usuario en CrugeSession ha caducado
+		// o ha sido cerrada por el administrador entonces 
+		// el usuario debera iniciar sesion manualmente nuevamente.
+
+		$app=Yii::app();
+		$request=$app->getRequest();
+		$cookie=$request->getCookies()->itemAt($this->getStateKeyPrefix());
+		if($cookie && !empty($cookie->value) && is_string($cookie->value) 
+				&& ($data=$app->getSecurityManager()->validateData(
+						$cookie->value))!==false)
+		{
+			// el valor de la cookie es seguro
+			$data=@unserialize($data);
+			if(is_array($data) && isset($data[0],$data[1],$data[2],$data[3]))
+			{
+				list($id,$name,$duration,$states)=$data;
+				// echo "--data es: id={$id},name={$name}, duration={$duration}--";
+				$factory = CrugeUtil::factory();
+				$_crugeuser = $factory->getICrugeStoredUserLoadModel($id);
+				// si _crugeuser es null hay exception y no continuara.	
+				if($this->beforeLogin($id,$states,true))
+				{
+					$this->changeIdentity($id,$name,$states);
+					// esto solo vuelve a darle vida a la cookie por mas tiempo
+					if($this->autoRenewCookie)
+					{
+						$cookie->expire=time()+$duration;
+						$request->getCookies()->add($cookie->name,$cookie);
+					}
+					// busca la ultima sesion cruge, reutilizandola, no crea
  1. Christian Salazar repo owner

    aqui se BUSCA el ultimo CrugeSession para este usuario, el cual se usara para MARCAR la identidad en CrugeWebUser, de modo que se sepa que ha iniciado sesion con ese objeto de control de CrugeSession.

+					// ninguna nueva, solo reutiliza.
+					$_crugesession = $factory->getICrugeSessionFindLastByUser($id);
+					if($_crugesession != null){
+						$this->setSessionId($_crugesession->primarykey);	
+						$this->afterLogin(true);
+					}
+					else{	
+						//	las credenciales estan aun en cookie, validas, pero
+						//	el usuario de cruge (al que hace referencia) ya no
+						//  tiene una Sesion valida dentro del sistema.
+						
+					}
+				}
+			}
+		}
+		else{
+			// las credenciales almacenadas han caducado
+		}
+	}
 
     /**
     se SUPONE que este metodo fue llamado tras un $identity->authenticate exitoso,
                 // ahora si...guarda el identificador de sesion que getId devolvera
 				$_SESSION['cruge_redirect_count']=0;
                 $this->setSessionId($usersession->getPrimaryKey());
-                $filtro->onLogin($usersession);
  1. Christian Salazar repo owner

    aqui es donde se GUARDA EN LA COOKIE al CrugeUserId ($id en este caso), para que luego al reabrir el browser se busque para ese ID al ultimo objeto valido de CrugeSession para ese usuario.

+				if($this->allowAutoLogin && ($duration > 0))
+					$this->saveToCookie($duration);
+				$filtro->onLogin($usersession);
                 return true;
             } else {
                 Yii::log(CHtml::errorSummary($usersession, "error al guardar una sesion"), "error");

models/ui/CrugeLogon.php

             $this->_identity = Yii::app()->user->um->getNewCrugeUser($this->username, $this->password, $this->authMode);
             $this->_identity->authenticate();
         }
-
         if ($this->_identity->hasErrors() == false) {
-            if (!Yii::app()->user->login($this->_identity)) {
+			$duration=0;
+			if($this->rememberMe){
+				$sys = Yii::app()->user->um->getDefaultSystem();
+				$duration = $sys->getn('sessionmaxdurationmins') * 60;
+			}
+			Yii::log(__METHOD__."\nintento iniciar sesion. duration=".$duration.", username=".$this->username,"info");
+			if (!Yii::app()->user->login($this->_identity, $duration)) {
                 if ($booleanThrowException == true) {
                     throw new CrugeException(Yii::app()->user->getLastError());
                 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.