Autenticazione

Sò che esiste il modulo user , è l’ho provato e funziona , siccome ci stò sbattendo la testa ma non riesco a familiarizzare con questo framework (sicuramente sono io il problema) ho provato a modificare la classe Useridentity che ho anche commentato , inserisco username e password e ottengo una pagina bianca…Mi domando come faccio a passare i parametri $username e $password che in un altro contesto sarebbero :




$username =$_POST['username'];

$password =$_POST['password'];



Questa la classe…




class UserIdentity extends CUserIdentity

{

	/**

	 * 

	 * @return boolean whether authentication succeeds.

	 */

	public function authenticate($username,$password){


		$sql="select * from  clienti where username='".$username."'and password='".$password."'and active=1";

		$connection=Yii::app()->db; //recupero il nome della connessione impostato nel config main

		$command=$connection->createCommand($sql); //eseguo la query o sbaglio?

		$rowCount=$command->execute();   // conto il numero di righe o sbaglio?


		if($rowCount==1){

			return true;

		}

		else {

			return false;

		}

	}

}



guardati come funziona il model UserLogin del modulo user.

Potresti darmi qualche info in + ? La funzione authenticate mi sembra la stessa tranne che per la gestione degli errori per il resto mi sembra tutto molto simile tranne che il model UserLogin non ha un metodo Login…

come ti hanno detto in precedenza guarda l’esempio iniziale che ti da yii.

In particolare il component UserIdentity, il model LoginForm e l’action Login.




public function rules()

	{

		return array(

			// email and password are required

			array('email, password', 'required'),

			// rememberMe needs to be a boolean

			array('rememberMe', 'boolean'),

			// password needs to be authenticated

			array('password', 'authenticate'), <--- Questa è importante

		);

	}



authenticate nelle rules, è importante. Richiama il metodo authenticate della classe UserLogin, come validatore della form e cerca di autenticare l’utente nell’applicazione.




public function authenticate($attribute,$params)

	{

		if(!$this->hasErrors())  // we only want to authenticate when no input errors

		{

			$identity=new UserIdentity($this->email,$this->password);

			$identity->authenticate();

			switch($identity->errorCode)

			{

				case UserIdentity::ERROR_NONE:

					$duration=$this->rememberMe ? Yii::app()->controller->module->rememberMeTime : 0;

					Yii::app()->user->login($identity,$duration);

					break;

				case UserIdentity::ERROR_EMAIL_INVALID:

					$this->addError("email",UserModule::t("Email is incorrect."));

					break;

				case UserIdentity::ERROR_STATUS_NOTACTIV:

					$this->addError("status",UserModule::t("You account is not activated."));

					break;

				case UserIdentity::ERROR_STATUS_BAN:

					$this->addError("status",UserModule::t("You account is blocked."));

					break;

				case UserIdentity::ERROR_PASSWORD_INVALID:

					$this->addError("password",UserModule::t("Password is incorrect."));

					break;

			}

		}

	}



Le variabili d’istanza email e password , dove vengono inizializzate?

Potete dirmi davvero dove si inizializzano le variabili pubbliche password e username di LoginForm?

posta il tuo codice Model, View e Action di riferimento, e vediamo cosa c’è che non va.

A prescindere dal mio codice , vorrei sapere dove il modulo user inizializza le variabili username e password ad esempio login form le utilizza ma dove sono inizializzate?

questa che posto qui sotto è la classe UserLogin.php che avevo detto di guardarti:

mi sembra che la risposta alla tua domanda sia già nelle prime righe della classe, che dici?




<?php


/**

 * LoginForm class.

 * LoginForm is the data structure for keeping

 * user login form data. It is used by the 'login' action of 'SiteController'.

 */

class UserLogin extends CFormModel

{

	public $email;

	public $password;

	public $rememberMe;


	/**

	 * Declares the validation rules.

	 * The rules state that email and password are required,

	 * and password needs to be authenticated.

	 */

	public function rules()

	{

		return array(

			// email and password are required

			array('email, password', 'required'),

			// rememberMe needs to be a boolean

			array('rememberMe', 'boolean'),

			// password needs to be authenticated

			array('password', 'authenticate'),

		);

	}


	/**

	 * Declares attribute labels.

	 */

	public function attributeLabels()

	{

		return array(

			'rememberMe'=>UserModule::t("Remember me next time"),

			'email'=>UserModule::t("username or email"),

			'password'=>UserModule::t("password"),

		);

	}


	/**

	 * Authenticates the password.

	 * This is the 'authenticate' validator as declared in rules().

	 */

	public function authenticate($attribute,$params)

	{

		if(!$this->hasErrors())  // we only want to authenticate when no input errors

		{

			$identity=new UserIdentity($this->email,$this->password);

			$identity->authenticate();

			switch($identity->errorCode)

			{

				case UserIdentity::ERROR_NONE:

					$duration=$this->rememberMe ? Yii::app()->controller->module->rememberMeTime : 0;

					Yii::app()->user->login($identity,$duration);

					break;

				case UserIdentity::ERROR_EMAIL_INVALID:

					$this->addError("email",UserModule::t("Email is incorrect."));

					break;

				case UserIdentity::ERROR_STATUS_NOTACTIV:

					$this->addError("status",UserModule::t("You account is not activated."));

					break;

				case UserIdentity::ERROR_STATUS_BAN:

					$this->addError("status",UserModule::t("You account is blocked."));

					break;

				case UserIdentity::ERROR_PASSWORD_INVALID:

					$this->addError("password",UserModule::t("Password is incorrect."));

					break;

			}

		}

	}

}



Questo l’action login di Sitecontroller




<?php


class SiteController extends Controller

{


	/**

	 * Displays the login page

	 */

	public function actionLogin()

	{

		$model=new LoginForm;


		// if it is ajax validation request

		if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}


		// collect user input data

		if(isset($_POST['LoginForm']))

		{

			$model->attributes=$_POST['LoginForm'];

			// validate user input and redirect to the previous page if valid

			if($model->validate() && $model->login())

				$this->redirect(Yii::app()->user->returnUrl);

		}

		// display the login form

		$this->render('login',array('model'=>$model));

	}




Scusami ma io non riesco ancora a vedere dove vengono passati i valori… o dentro $_POST[‘LoginForm’] ci sono sia username che password? che poi vengono passate a $model->attributes ?

guardati il post che ti arriva dal controller per capire meglio

quello che ti interessa è:

$model->attributes=$_POST[‘LoginForm’];

$_POST[‘LoginForm’] è un array che contiene i tuoi campi.

Alcune Domande :

$_POST[‘LoginForm’][0] è l’username ?

$_POST[‘LoginForm’][1] è la password ?

SiteController non istanzia nessun UserLogin ,perchè non è questo che mi serve :




/**

 * LoginForm class.

 * LoginForm is the data structure for keeping

 * user login form data. It is used by the 'login' action of 'SiteController'.

 */




ma il LoginController del componente User,o sbaglio?

Poi ,l’actionLogin di LoginController:




public function actionLogin()

	{

		if (Yii::app()->user->isGuest) {

			$model=new UserLogin;

			// collect user input data

			if(isset($_POST['UserLogin']))

			{

				$model->attributes=$_POST['UserLogin'];

				// validate user input and redirect to previous page if valid

				if($model->validate()) {

					$this->lastViset();

					if (Yii::app()->getBaseUrl()."/index.php" === Yii::app()->user->returnUrl)

						$this->redirect(Yii::app()->controller->module->returnUrl);

					else

						$this->redirect(Yii::app()->user->returnUrl);

				}

			}

			// display the login form

			$this->render('/user/login',array('model'=>$model));

		} else

			$this->redirect(Yii::app()->controller->module->returnUrl);

	}



Istanzia la classe UserLogin (quella che mi serve) , , e fà :


$model->attributes=$_POST['UserLogin'];

Non vedo nessuna funzione "attributes" che valorizza le variabili nella classe UserLogin.

Scusami ma se non capisco bene queste fasi iniziali penso di non poter mai utilizzare questo framework…

decidi cosa usare per fare questa login form:

-o utilizzi il login che ti mette a disposizione l’applicazione demo

-oppure puoi utilizzare un modulo apposito per la gestione delle utenze, che quindi ti fornisce anche un’altro metodo di login, che funziona in maniera simile a quello sopra riportato ma che si presenta un minimo più avanzato.

Partiamo da quello base:

SiteController:




         /**

	 * Displays the login page

	 */

	public function actionLogin()

	{

		$model=new LoginForm;


		// if it is ajax validation request

		if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}


		// collect user input data

		if(isset($_POST['LoginForm']))

		{

			$model->attributes=$_POST['LoginForm'];

			// validate user input and redirect to the previous page if valid

			if($model->validate() && $model->login())

				$this->redirect(Yii::app()->user->returnUrl);

		}

		// display the login form

		$this->render('login',array('model'=>$model));

	}



LoginForm.php (il modello della tua form)




class LoginForm extends CFormModel

{

	public $username;

	public $password;

	public $rememberMe;


	private $_identity;


	/**

	 * Declares the validation rules.

	 * The rules state that username and password are required,

	 * and password needs to be authenticated.

	 */

	public function rules()

	{

		return array(

			// username and password are required

			array('username, password', 'required'),

			// rememberMe needs to be a boolean

			array('rememberMe', 'boolean'),

			// password needs to be authenticated

			array('password', 'authenticate'),

		);

	}


	/**

	 * Declares attribute labels.

	 */

	public function attributeLabels()

	{

		return array(

			'rememberMe'=>'Remember me next time',

		);

	}


	/**

	 * Authenticates the password.

	 * This is the 'authenticate' validator as declared in rules().

	 */

	public function authenticate($attribute,$params)

	{

		if(!$this->hasErrors())

		{

			$this->_identity=new UserIdentity($this->username,$this->password);

			if(!$this->_identity->authenticate())

				$this->addError('password','Incorrect username or password.');

		}

	}


	/**

	 * Logs in the user using the given username and password in the model.

	 * @return boolean whether login is successful

	 */

	public function login()

	{

		if($this->_identity===null)

		{

			$this->_identity=new UserIdentity($this->username,$this->password);

			$this->_identity->authenticate();

		}

		if($this->_identity->errorCode===UserIdentity::ERROR_NONE)

		{

			$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days

			Yii::app()->user->login($this->_identity,$duration);

			return true;

		}

		else

			return false;

	}

}



la tua form, quindi la view:

views/site/login




<?php

$this->pageTitle=Yii::app()->name . ' - Login';

$this->breadcrumbs=array(

	'Login',

);

?>


<h1>Login</h1>


<p>Inserire le credenziali per effettuare il login:</p>


<div class="form">

<?php $form=$this->beginWidget('CActiveForm', array(

	'id'=>'login-form',

	'enableClientValidation'=>true,

	'clientOptions'=>array(

		'validateOnSubmit'=>true,

	),

)); ?>


	<div class="row">

		<?php echo $form->labelEx($model,'username'); ?>

		<?php echo $form->textField($model,'username'); ?>

		<?php echo $form->error($model,'username'); ?>

	</div>


	<div class="row">

		<?php echo $form->labelEx($model,'password'); ?>

		<?php echo $form->passwordField($model,'password'); ?>

		<?php echo $form->error($model,'password'); ?>

	</div>


	<div class="row buttons">

		<?php echo CHtml::submitButton('Login'); ?>

	</div>


<?php $this->endWidget(); ?>

</div><!-- form -->



e poi c’è il componenete UserIdentity.

Sostanzialmente in questo snippet di codice che qui ti ho incollato, si evidenziano alcune delle funzionalità che il framework offre, se tu avessi cominciato a studiacchiarti la guida ufficiale, magari qualcosa in più l’avresti capita.

Partiamo dal controller:

-$model=new LoginForm; (creo un nuovo model di tipo LoginForm)

-$this->render(‘login’,array(‘model’=>$model)); (renderizzo la view login, passandogli come argomento il model appena creato).

Il Model:

-public $username;

public $password;

public $rememberMe;

LoginForm è composta dai suddetti attributi con regole di validazione che trovi in:

public function rules()

{


	return array(


		// username and password are required


		array('username, password', 'required'),


		// rememberMe needs to be a boolean


		array('rememberMe', 'boolean'),


		// password needs to be authenticated


		array('password', 'authenticate'),


	);


}

quindi gli attributi username e passowrd sono required (obbligatori),rememberMe di tipo booleano, password inoltre ha un metodo personalizzato di validazione che è authenticate.

Se tutte queste regole non sono validate (compreso authenticate) la validazione di questa form non va a buon fine.

questo è authenticate:

public function authenticate($attribute,$params)

{


	if(&#33;&#036;this-&gt;hasErrors())


	{


		&#036;this-&gt;_identity=new UserIdentity(&#036;this-&gt;username,&#036;this-&gt;password);


		if(&#33;&#036;this-&gt;_identity-&gt;authenticate())


			&#036;this-&gt;addError('password','Incorrect username or password.');


	}


}

-La view (quindi la form di login):

viene dichiarata in un modo particolare:

<?php $form=$this->beginWidget(‘CActiveForm’, array(…

gli attributi vengono dichiarati in questa maniera:

<div class="row">

	&lt;?php echo &#036;form-&gt;labelEx(&#036;model,'username'); ?&gt;


	&lt;?php echo &#036;form-&gt;textField(&#036;model,'username'); ?&gt;


	&lt;?php echo &#036;form-&gt;error(&#036;model,'username'); ?&gt;


&lt;/div&gt;

$model rappresenta il LoginForm creato nel SiteController, username un suo attributo.

e poi chiusa … <?php $this->endWidget(); ?> in questa maniera

Quando effettui il submit, il controller farà la validazione di questa form quindi andrà a controllare che tutte le regole di validazione siano ok.

La form in questione,riferita al tuo modello LoginForm,avrà nel POST

$_POST[‘LoginForm’][‘username’] //LoginForm rappresenta il modello, username un suo attributo.

$_POST[‘LoginForm’][‘password’]

$model->attributes=$_POST[‘LoginForm’]; è un metodo che il framework ti offre per settare gli attributi proprio del tuo modello,altrimenti dovresti fare:

$model->username = $_POST[‘LoginForm’][‘username’];

$model->password = $_POST[‘LoginForm’][‘password’];

e così via… per form più grosse, ti evita un bel lavorone (inutile e di non dimenticarti alcun attributo).

Spero di essere stato chiaro.

Quindi io ho cercato di modificare UserIdentity per prendere i dati dal db , il controller e il model ki ho lasciati invariati in questo modo :





<?php


/**

 * UserIdentity represents the data needed to identity a user.

 * It contains the authentication method that checks if the provided

 * data can identity the user.

 */

class UserIdentity extends CUserIdentity

{

	/**

	 * Authenticates a user.

	 * The example implementation makes sure if the username and password

	 * are both 'demo'.

	 * In practical applications, this should be changed to authenticate

	 * against some persistent user identity storage (e.g. database).

	 * @return boolean whether authentication succeeds.

	 */

	public $username;

	public $password;





	function __construct($username,$password){


		$this->username=$username;

		$this->password=$password;




	}




	public function authenticate()

	{

		


        $sql="select * from  utenti where username='".$this->username."'and password='".$this->password."'and active=1";

        $connection=Yii::app()->db; //recupero il nome della connessione impostato nel config main giusto?

        $command=$connection->createCommand($sql); 

        $rowCount=$command->query();   //eseguo la query giusto?

        $num = count($rowCount); // conto il numero di righe o sbaglio?


        if($num==1){

            return true;

        }

        else {

            return false;

        }

        

	}

}



Ma non eseguo il login …

questa è la classe UserIdentity del modulo Users, ovviamente modificala a seconda delle tue asigenze, ad esempio se vuoi al posto di fare la query con sql puoi usare activerecord messo a disposizione da yii ($user=User::model()->notsafe()->findByAttributes()). Fai qualche var_dump e un pò di debug, per capire dove la cosa si blocca, oppure facci sapere l’errore che ti viene fuori.




class UserIdentity extends CUserIdentity

{

	private $_id;

	const ERROR_EMAIL_INVALID=3;

	const ERROR_STATUS_NOTACTIV=4;

	const ERROR_STATUS_BAN=5;

	/**

	 * Authenticates a user.

	 * The example implementation makes sure if the username and password

	 * are both 'demo'.

	 * In practical applications, this should be changed to authenticate

	 * against some persistent user identity storage (e.g. database).

	 * @return boolean whether authentication succeeds.

	 */

	public function authenticate()

	{

		$user=User::model()->notsafe()->findByAttributes(array('email'=>$this->username));

		

		if($user===null)

			$this->errorCode=self::ERROR_EMAIL_INVALID;

			

		else if(Yii::app()->getModule('user')->encrypting($this->password)!==$user->password)

			$this->errorCode=self::ERROR_PASSWORD_INVALID;

		else if($user->status==0&&Yii::app()->getModule('user')->loginNotActiv==false)

			$this->errorCode=self::ERROR_STATUS_NOTACTIV;

		else if($user->status==-1)

			$this->errorCode=self::ERROR_STATUS_BAN;

		else {

			$this->_id=$user->id;

			$this->setState('nomecompleto', $user->cognome.' '.$user->nome);

			$this->errorCode=self::ERROR_NONE;

		}

		return !$this->errorCode;

	}

    

    /**

    * @return integer the ID of the user record

    */

	public function getId()

	{

		return $this->_id;

	}

}



Son riuscito a loggarmi :

questo il mio UserIdentity :





class UserIdentity extends CUserIdentity

{

       

        /**

         * Authenticates a user.

         * The example implementation makes sure if the username and password

         * are both 'demo'.

         * In practical applications, this should be changed to authenticate

         * against some persistent user identity storage (e.g. database).

         * @return boolean whether authentication succeeds.

         */


        public function authenticate()

        {

                

	        $sql="select * from  utenti where username='".$this->username."'and password='".$this->password."'and active=1";

	        $connection=Yii::app()->db; //recupero il nome della connessione impostato nel config main giusto

	        $command=$connection->createCommand($sql); 

	        $rowCount=$command->query();   //eseguo la query ritorna un array con tutti i record

	        $num = count($rowCount); // conto il numero di righe




	        if($num==1){  //se uguale a 1 cioè esiste un record ritorna true 

 	            return true;

	        }

	        else {

	            return false;

	        }

	        

        }

}






Prima domanda , nella documentazione ufficiale dice che per contare i record possiamo usare :





// get the number of rows satisfying the specified condition

$n=Post::model()->count($condition,$params);




Come specifico le condizioni (user = all’user del db e password = pw del db e active =1) ?

$params a cosa serve?

Questa la funzione login di Login Form :





public function login()

	{	

		$controllo=$this->_identity->authenticate();


		if($this->_identity===null)

		{

			$this->_identity=new UserIdentity($this->username,$this->password);

			$this->_identity->authenticate();

		}

		if($controllo==true)

		{

			$duration=$this->rememberMe ? 3600*24*30 : 0; // 30 days

			Yii::app()->user->login($this->_identity,$duration);

			return true;

		}

		else

			return false;

	}




Poichè UserIdentity ritorna un boolean , ho utilizzato il boolean come condizione del if , è corretto come approccio?

Questa la function actionLogin di UtentiController (copiata da siteController):





	public function actionLogin()

	{

		$model=new LoginForm;


		// if it is ajax validation request

		if(isset($_POST['ajax']) && $_POST['ajax']==='login-form')

		{

			echo CActiveForm::validate($model);

			Yii::app()->end();

		}


		// collect user input data

		if(isset($_POST['LoginForm']))

		{

			$model->attributes=$_POST['LoginForm'];

			// validate user input and redirect to the previous page if valid

			if($model->validate() && $model->login())

				$this->redirect(Yii::app()->user->returnUrl);

		}

		// display the login form

		$this->render('login',array('model'=>$model));

	}




Come funziona il redirect ? OPerchè mi rimanda all’index del site invece che a quello di Utenti ?

questo è il modo in cui si usa count()




    $n=Users::model()->count('username=:username,password=:password,active=:active', array('username' => $this->username,'password'=>$this->password,'active'=>1));



oppure puoi utilizzare countByAttributes




$n=Users::model()->countByAttributes(array(

            'username'=> $this->username, 'password'=>$this->password,'active'=>1

        ));



per il returnUrl dovresti settarlo da qualche parte:




public $returnUrl = array("/user/profile");