Formulari II: PHP + MySQL. Cookies i variables de sessió

De wikijoan
Salta a la navegació Salta a la cerca

El Formulari ataca una base de dades

Reprenem el formulari de la tenda del Jaume Balmes. L'objectiu serà que quan acabem d'omplir les dades del formulari es faci una inserció a la base de dades (a la taula CLIENT). Després també haurem de fer un formulari de login/password que ens digui si aquest usuari existeix, i recuperar la identitat de l'usuari en cas de què existeixi.

  • crearem la base de dades jbalmes
  • crearem la taula CLIENT
  • programarem el codi PHP (registre.php) per tal que quan omplim el formulari de registre s'insereixi una fila en la taula CLIENT (hauríem de comprovar prèviament que el login no existeix).
  • programarem el fitxer login.php per tal de què els usuaris registrats inicïin una sessió. Es poden donar tres possibilitats: 1) existeix login i pwd a la bd; 2) el login no existeix; 3) el login existeix però el pwd no és correcte. A més a més marcarem amb un checkbox la possibilitat de què l'usuari sigui recordat entre sessions.
  • quan un usuari es loga correctament hem d'iniciar una sessió (objecte Session), per tal de què aquest usuari estigui ben identificat en les diferents accions que faci durant la sessió (navegar pels productes, tenir una cistella de compra,...).

Pots comprovar el funcionament de la web del Balmes, ara ja accedint a la base de dades:

Base de dades

SET NAMES 'UTF8';

CREATE DATABASE jbalmes DEFAULT CHARACTER SET utf8;

USE jbalmes;

DROP TABLE LOGIN;

CREATE TABLE LOGIN(
id_login smallint primary key,
NIF char(9) not null,
nom varchar(30) not null,
cognoms varchar(30) not null,
login varchar(10) not null,
clau varchar(50) not null,
direccio varchar(30),
CP char(5),
poblacio varchar(30),
telefon varchar(20) not null,
mobil varchar(30),
mail varchar(30)
) TYPE=InnoDB;

Connexió a la base de dades

Fitxer open_db.php:

<?php
$conn = mysqli_connect("localhost", "login", "pwd", "jbalmes");
if (!$conn) {
    die("Connection failed: " . mysqli_connect_error());
}
?>

Fitxer close_db.php:

<?php
mysqli_close($conn); 
?>

Registre: inserció i consulta a la base de dades

Fixa't que volem que els passwords es guardin encriptats en la base de dades. Per fer-ho és necessàri tenir instal.lada la llibreria mcrypt, que és l'habitual en el cas de voler encriptar passwords.

Fitxer registre.php. El fitxer registre.php ja el vas treballar en l'anterior pràctica, però ara té extensió PHP i inclou el següent codi:

<?php include("head.php"); ?>
<?php include("cap_esq_dreta.php"); ?>

<!-- ##### Zona principal ########################################################## -->

    <div id="zona_ppal">
    <div id="contingut1">

		<?php

		$vnif=trim($_POST['nif']);
		$vnom=trim($_POST['nom']);
		$vcognoms=trim($_POST['cognoms']);
		$vlogin=trim($_POST['login']);
		$vpwd=trim($_POST['pwd']);
		$vdireccio=trim($_POST['direccio']);
		$vcp=trim($_POST['cp']);
		$vpoblacio=trim($_POST['poblacio']);
		$vtelefon=trim($_POST['telefon']);
		$vmobil=trim($_POST['mobil']);
		$vmail=trim($_POST['mail']);

		$key = '123456789012345678901234567890123456789012345678901234567890';
		$vpwd = mcrypt_cbc(MCRYPT_RIJNDAEL_128, substr($key,0,32), $vpwd, MCRYPT_ENCRYPT,substr($key,32,16));
		$vpwd=bin2hex($vpwd);


		if ($vnif!="") {

		include("open_db.php");
		$sql = "select max(id_login) as max_id_login from LOGIN";
		$result = mysql_query($sql);

		$row = mysql_fetch_assoc($result);

		if (!isset($row['max_id_login'])){
			$vid_login=1;
		} else {
			$vid_login=$row['max_id_login']+1;
		}

		$sqlstring  = "INSERT INTO LOGIN ";
		$sqlstring .= "(id_login,NIF,nom,cognoms,login,clau,direccio,CP,poblacio,telefon,mobil,mail) values (";
		$sqlstring .= $vid_login . ",'" . $vnif . "','" . fixQuotes($vnom) . "','" . fixQuotes($vcognoms) . "','" . fixQuotes($vlogin) . "','" . $vpwd . "',";
		$sqlstring .= "'" . fixQuotes($vdireccio) . "','" . $vcp . "','" . fixQuotes($vpoblacio) . "','" . $vtelefon . "','" . $vmobil . "','" . $vmail . "')";

		//echo $sqlstring;
		$result = mysql_query($sqlstring);


		echo "<p><img src=\"img/user2_16.gif\" alt=\"user added\" /><b>user ".$vnom." s'ha registrat correctament</b></p>";

		include("close_db.php");

		}
		?>

		<form name="form_registre" method="post" action="registre.php" >

                ...

		</form>


    </div> <!-- fi contingut1-->		

    </div> <!-- fi zona_ppal-->


<?php include("peu.php"); ?>

<?php

function fixQuotes($cadena){

	return str_replace("'","''",$cadena);

}



function fixSlash($cadena){

	return str_replace("\\","\\\\",$cadena);

}
?>

En aquest moment ja pots consultar la taula LOGIN de la base de dades, i veure com la clau es guarda encriptada.

Fer login: iniciar una sessió

D'una banda tenim el fitxer login.php (un formulari bàsic amb el login i password, i un checkbox), que envia les dades a login2.php.

El formulari login.php mira si el navegador recorcda el login i pwd entre sessions, que s'ha establert amb una cookie.

Fitxer login.php: (mira si hi ha les cookies per al login i pwd)

<?php include( "head.php" ); ?>
<body>
<?php include( "cap_esq_dreta.php" ); ?>
<?php //session_unset(); ?>

<!-- ##### Zona principal ########################################################## -->
    <div id="zona_ppal">
			<div id="contingut1">

				<form name="form_login" method="post" action="login2.php" >	
				<fieldset>
                                <h1><legend><img src="img/user2_24.gif" /> Login</legend></h1>

					<div class="required">
					<label style="width: 140px;" for="login">login:</label>
					<input id="txt" name="login" size="8" maxlength="10" style="width:100px;" value="<?php if (isset($_COOKIE['login_balmes'])) { echo $_COOKIE['login_balmes']; } ?>" />
					</div>

					<div class="required">
					<label style="width: 140px;" for="pwd">Clau:</label>
					<input id="txt" name="pwd" type="password" size="8" maxlength="10" style="width:100px;" value="<?php if (isset($_COOKIE['pwd_balmes'])) { echo $_COOKIE['pwd_balmes']; } ?>" />
					</div>
					<div class="optional">
					<label style="width: 140px;" for="pwd">Recordar login/pwd:</label>
					<input type="checkbox" name="chk_recordar" value="" checked="true" />
					</div>
				</fieldset>

				<fieldset>
					<div class="submit">
					<div>
					<input type="submit" class="inputSubmit" style="margin-left: 75px;" value="Login"/> <!-- el styke posiciona el submit -->
					</div>
					</div>
				</fieldset>

			</form>
			</div>

			<div id="contingut2">
			</div>

    </div> <!-- fi zona_ppal-->

<?php
include( "peu.php" );
?>

Fitxer login2.php: (si cal, estableix les cookies per a login i pwd)

<?php

header ("Content-Type: text/html; charset=iso-8859-1");

session_start();

$vlogin=trim($_POST['login']);
$vpwd=trim($_POST['pwd']);
$vrecordar=$_POST['chk_recordar'];

$key = '123456789012345678901234567890123456789012345678901234567890';
$vpwd2 = mcrypt_cbc(MCRYPT_RIJNDAEL_128, substr($key,0,32), $vpwd, MCRYPT_ENCRYPT,substr($key,32,16));
$vpwd2=bin2hex($vpwd2);

include 'open_db.php';

$sql = "SELECT * FROM LOGIN WHERE login='" . $vlogin . "'";
$result = mysql_query($sql);

if (!$result) {
    $message  = 'Invalid query: ' . mysql_error() . "\n";
    die($message);
}


if (mysql_num_rows($result)>0){ //existeix el login
	$row = mysql_fetch_assoc($result);
	if ($vpwd2==$row['clau']){ //login correcte
		ini_set('session.auto_start', '1');
		$_SESSION['id_login']=$row['id_login'];
		$_SESSION['login']=$vlogin;

                if (isset($vrecordar)) {
                    setcookie ("login_balmes", $vlogin, time() + 3600*24*365);
                    setcookie ("pwd_balmes", $vpwd, time() + 3600*24*365);
                } else {  
                    setcookie ("login_balmes", "");
                    setcookie ("pwd_balmes", "");  //compte! el password es guarda sense encriptar                   
                }
		header("Location: productes.php"); //redirecció

	} else {	//no coincideixen els passwords

		$str = "<p style=\"color=#ff0000\"><b>passwords doesn't match</b></p>";
	}
} else {
	$str = "<p style=\"color=#ff0000\"><b>Login doesn't exist</b></p>"; //tr//
}

include 'close_db.php';

if (str) {
	include("head.php");
	include("cap_esq_dreta.php");
?>
<!-- ##### Zona principal ########################################################## -->
    <div id="zona_ppal">
        <div id="contingut1">
	<?php echo $str ?>        
    </div> <!-- fi contingut1-->		
    </div> <!-- fi zona_ppal-->

<?php
}

?>

Hi ha diferents coses que s'ha de comentar.

Si l'usuari es valida correctament hi ha una redirecció automàtica a la pàgina productes.php (que està buida), amb la comanda:

header("Location: productes.php"); //redirecció

Per tal de què funcioni és necessari que prèviament no s'hagi escrit res per la pantalla. L'aplicatiu gestiona correctament el fet de què l'usuari no existeix, o que els passwords no coincideixen.

Si vols aprofundir en la relació que hi ha entre les cookies, les variables de sessió, i com podem modificar-les amb un formulari, pots llegir l'article:

Aquesta tècnica s'ha utilitzat a http://arthropoda.joanillo.org. En el formulari de configuració (http://arthropoda.joanillo.org/configuration.php) s'estableix l'idioma predeterminat, el tamany de les fotos, i el número de fotos que vols veure per a cada espècie. Aquesta informació es guarda per a la sessió actual. i es guarden les cookies per tal de què aquesta configuració estigui disponible en la següent sessió.

Gestió de les sessions

La vida de les variables de sessió és la següent:

  • head.php: iniciem la sessió
<?php session_start(); ?>
  • login2.php: si l'usuari es valida correctament, s'inicialitzen les variables de sessió:
ini_set('session.auto_start', '1');
$_SESSION['id_login']=$row['id_login'];
$_SESSION['login']=$vlogin;
  • Funcionalitat de la capçalera (cap_esq_dreta.php): si l'usuari està registrat, apareix el seu nom a la capçalera (esquerra); i a la dreta es canvia l'etiqueta Login per Logout
		<div class="subcapcalera">
			 
			<div id="barra" class="barra"><a href="http://www.jaumebalmes.org">IES Jaume Balmes</a> » <a href="index.php">Tenda Online</a></div>
			<a class="login2"><?php if (isset($_SESSION['login'])) echo "log: ".$_SESSION['login']; ?></a>
			<?php if (!isset($_SESSION['login'])) { ?>
			<a class="login" href="./login.php">Login</a>
			<?php } else { ?>
			<a class="login" href="./logout.php">Logout</a>			
			<?php } ?>

		</div>
  • logout.php. Abandonem l'aplicatiu destruint les variables de sessió (però si interessa les cookies ens recorden el nostre login i pwd). Ens redirigim a login.php
<?php
	session_start();
	session_unset(); //kills all session variables 
	header("Location: login.php");
?>

Codi font

Pots trobar la web del Balmes i els fitxers que necessites a:



creat per Joan Quintana Compte, gener 2019