PHP Sesións

De MediaWiki
Ir a la navegación Ir a la búsqueda

Concepto

  • Unha sesión 'dura' mentres un usuario está conectado a un sitio web.
  • Empeza cando se conecta por primeira vez.
  • Remata cando sae do sitio web ou leva un tempo de inactividade indicado pola directiva session.gc_maxlifetime no arquivo php.ini. Por defecto está establecido en 1440 segundos (24 minutos).


  • Dentro da sesión dun usuario é posible crear variables que manterán o seu valor mentres o usuario teña a sesión activa, e poderemos obter ditos valores dende calquera páxina do sitio web.
É importante sinalar que as variables de sesión SE GARDAN NO SERVIDOR a diferenza das cookies que se envían ao cliente e se gardan no seu computador.


  • Pódese empregar para pasar información 'importante' ou confidencial.




Existen certos parámetros que se poden configurar no php.ini do servidor web apache:

  • session.use_cookies: Indica se deben usar cookies (1) ou propagación na URL (0) para gardar o SID.
  • session.use_only_cookies: Debe activarse (1) cando usas cookies para gardar os SIDs, e non queres recoñecer os SIDs que se poidan pasar como parte da URL (este método pódese usar para usurpar o identificador doutra persoa).
  • session.save_handler: Utilízase para indicar a PHP como debe gardar os datos da sesión do usuario. Existes catro opcións: en ficheiros (files), en memoria (mm), nunha base de datos SQLite (sqlite) ou usando funcións que debe definir o programador (user). O valor por defecto (files) funcionará sen problemas na maioría dos casos.
  • session.name: Determina o nome da cookie que se utilizará para gardar o SID. O seu valor por defecto é PHPSESSID.
  • session.auto_start: O seu valor por defecto é 0, e neste caso debes usar a función session_start para xestionar o inicio das sesións. Se usas sesións no sitio web, pode ser boa idea cambiar o seu valor a 1 para que PHP active automaticamente a xestión de sesións.
  • session.cookie_lifetime: Se usas a URL para propagar o SID, este perderase cando peches o teu navegador. Sen embargo, se usas galletas, o SID manterase mentres non se destrúa a galleta. No seu valor por defecto (0), as galletas destrúense cando pechas o navegador. Se queres que o SID se manteña durante máis tempo, debes indicar nesta directiva ese tempo en segundos.
  • session.gc_maxlifetime: Indica o tempo en segundos que se debe manter activa a sesión, aínda que non haxa ningunha actividade por parte do usuario. O seu valor por defecto é 1440. Iso é, pasados 24 minutos dende a última actividade por parte do usuario, a súa sesión péchase automaticamente.


Máis información en php.net

Uso

Incializar

  • Cada vez que se inicia unha sesión, se crea un identificador único (ID) o cal pode ser pasado dunha páxina a outra pola URL ou por medio de cookies, se se ten habilitado o uso das mesmas.
  • Por motivos de seguridade se recomenda pasar o ID a través de cookies e non da URL.


  • Se se quere 'obrigar' ao usuario que utilice as cookies para pasar o ID se pode modificar o arquivo php.ini:
session.use_only_cookies = 1
Nota: Se estamos non aloxamento compartido, non teremos acceso ao arquivo php.ini, polo que poderemos crear un arquivo .htaccess no noso sitio web e engadir dita directiva ao mesmo.


  • Para iniciar ou reanudar unha sesión necesitamos chamar á función session_start() (a no ser que teñamos activida a directiva session.auto_start no php.ini).
É importante lembrar que debemos chamar a dita función sempre que fagamos uso de variables de sesión.
Dita chamada ten que facerse antes de enviar nada ao explorador do cliente (é dicir, facer un echo/printf ou calquera outra función que envíe algunha información ao navegador do cliente).
Normalmente sitúase ao principio da páxina php.
Isto é debido a que o ID da sesión envíase como encabezado HTTP ao utilizar unha cookie.



Usar

  • Unha vez chamada podemos crear / utilizar as variables de sesión da forma: $_SESSION['variable'] = "valor";
Unha vez dado o valor, podemos acceder a dita información dende calquera páxina mentres non eliminemos a variable de sesión.


Por exemplo:
 1 <?php
 2 // Inicializamos a sesión ou recuperamos a sesión anterior
 3 session_start();
 4 
 5 // Se é a primeira vez a variable non existe
 6 if (isset($_SESSION['visitas']))
 7     $_SESSION['visitas']++;  // A variable de sesión existe e aumentamos o valor
 8 else
 9     $_SESSION['visitas'] = 0; // A variable de sesión non existe e polo tanto inicializamos a variable
10 ?>




Borrar

  • Se queremos borrar os valores gardados nas variables de sesión:
  • Podemos chamar á función unset($_SESSION['var']); dentro dunha páxina coa sesión iniciada.
Por exemplo:
1 <?php
2     session_start();
3 
4      .......
5 
6     unset($_SESSION['nome']);
7 ?>
  • Tamén podemos chamar á función session_unset() coa sesión iniciada, que borra todas as variables de sesión da memoria.
1 <?php
2 session_start();
3 .....
4 session_unset();
5 ?>
Por exemplo:
1 <?php
2 session_start();
3 .....
4 session_destroy();
5 ?>
Nota: A sesión ten que estar iniciada antes de chamar a session_destroy().
Atención: Esta función elimina os datos de sesión gardados no servidor pero non elimina a cookie (método por defecto) que identifica a sesión e que se garda no computador do cliente conectado. Dita cookie seguirá existindo ata que expire ou o cliente peche o navegador.
Se queremos borrala teremos que executar o seguinte código:
1 <?php
2 session_start();
3 
4 .....
5 
6 session_destroy();
7 setcookie(session_name(),'',0,'/');
8 ?>


  • Lembrar que $_SESSION é un array e polo tanto podemos percorrelo e borrar todos os elementos:
1 <?php
2 foreach(array_keys($_SESSION) as $k) unset($_SESSION[$k])
3 ?>


Basicamente o que indica é que cando facemos un session_start() estamos cargando os datos gardados no disco do servidor no array global $_SESSION.
Cando facemos un session_unset() estamos a borrar ese array, pero os datos seguen gardados no disco ata que remata de procesar a páxina, momento en que se pasan os datos do array (borrados) a disco, borrando os datos.
Cando facemos un session_destroy() os datos gardados no disco do servidor son borrados, pero a copia local gardada na variable $_SESSION segue existindo na páxina que se está a procesar.


  • A orde correcta para eliminar todas as variables de sesión e que deixen de ser válidas na páxina que se está a procesar, eliminando o id de sesión gardado en forma de cookie no computador do cliente sería:
1 <?php
2 session_start();
3 .....
4 session_unset();
5 session_destroy();
6 setcookie(session_name(),'',0,'/');
7 ?>



Exemplo

  • Vexamos un exemplo:
  • Arquivo UD4_session_Ex1_paxina1.php:
 1 <?php
 2     session_start();
 3 ?>
 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 5     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 6 
 7 <html>
 8     <head>
 9         <meta charset="UTF-8">
10         <title></title>
11     </head>
12     <body>
13 <?php
14     $_SESSION['nome']='angel';
15 
16 ?>
17         <h1>Posto o valor da variable session 'nome' a Angel.</h1>
18         <h2>Pulsa <a href='UD4_session_Ex1_paxina2.php'> para ver o seu valor</a> noutra páxina...</h2>.
19         
20         
21     </body>
22 </html>

Php session 1.jpg

  • Arquivo UD4_session_Ex1_paxina2.php:
 1 <?php
 2     session_start();
 3 ?>
 4 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 5     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 6 
 7 <html>
 8     <head>
 9         <meta charset="UTF-8">
10         <title></title>
11     </head>
12     <body>
13 <?php
14      printf("<h1>O valor da variable sesión é: %s</h1>",$_SESSION['nome']);
15      printf("<h2>O valor do ID de sesión é: %s</h2>",  session_id());
16 
17 ?>
18      <h2>Pulsa <a href='UD4_session_Ex1_paxina3.php'> para borrar o seu valor</a>...</h2>.
19         
20     </body>
21 </html>

Php session 2.jpg


  • Arquivo UD4_session_Ex1_paxina3.php:
 1 <?php
 2     session_start();
 3 
 4 
 5     session_unset();  // Poderíamos poñer: session_unset['nome']
 6     session_destroy();
 7     setcookie(session_name(),'',0,'/');
 8 
 9 
10     // Lembrar que o session_id segue estando gardado como cookie no cliente.
11     // Se queredes borrala teredes que poñer: setcookie(session_name(),'',0,'/');
12 
13 ?>
14 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
15     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
16 
17 <html>
18     <head>
19         <meta charset="UTF-8">
20         <title></title>
21     </head>
22     <body>
23 <?php
24     printf("<h1>O valor da variable sesión é: %s</h1>",$_SESSION['nome']);
25     printf("<h2>O valor do ID de sesión é: %s</h2>",  session_id());
26 
27 ?>
28      <h2>Pulsa <a href='UD4_session_Ex1_paxina1.php'> para volver a darlle un valor</a>...</h2>.
29         
30     </body>
31 </html>

Php session 3.jpg



  • Podemos comprobar como dende o servidor se envía unha cookie ao cliente para que se garde o identificador de sesión e así o servidor é capaz de identificar ao cliente.


  • Por iso é importante que cando un usuario decida saír dun programa no que estea autenticado, debe premer a opción saír, xa que un usuario podería obter o id da sesión gardada localmente, modificar a súa id cun plugin calquera e acceder á información de sesión gardada no servidor.
  • O uso da URL para pasar o identificador de sesión (se non temos habilitado o uso de cookies) non é recomendable, xa que é visualmente accesible para calquera e se queremos compartir unha URL estariamos compartindo tamén o noso identificador de sesión.
  • Tamén se recomenda limitar o tempo de vida dunha cookie. Este parámetro se pode configurar coa directiva session.cookie_lifetime tempo_en_segundos no que indicamos o tempo en segundos que vai ter validez a cookie enviada ao navegador. O valor por defecto é de 0, que significa que a cookie será válida ata que se pecha o navegador.




Ataques CSRF (Cross-Site Request Forgery)

  • Xa vimos na UD2 desta wiki, diferentes técnicas para evitar ataques cando empregamos formulario.
Existe outro ataque que se pode empregar, consistente en que ao meu sitio web veñan os datos dun formulario dende outro sitio web diferente (é dicir, que se faga unha operación post/get dende un formulario diferente ao que o meu sitio web envía). É o que se coñece como CSRF.
Para evitalo, se fai uso das variables de sesión para xerar un código único ao cargar o formulario de tal forma que cando o usuario envía os datos do formulario se comproba que dito código é igual ao enviado ao cliente. Se non o fora, non se deixaría facer a operación cós datos do formulario.

O código para implementalo sería:

Xerar o Token: Ao cargar o formulario, xera un token único e gardao nunha variable de sesión.

session_start();
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));


Incorporar o Token no Formulario: Inclúe este token como un campo oculto dentro do teu formulario HTML.

<form action="procesar.php" method="post">
    <!-- Outros campos -->
    <input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">
    <input type="submit" value="Enviar">
</form>


Verificar o Token: Cando o formulario se envíe, compara o token recibido có que está almacenado na variable de sesión.

session_start();
if ($_POST['csrf_token'] !== $_SESSION['csrf_token']) {
    // Os tokens non coinciden, pode ser un intento de CSRF.
    die('Acción non autorizada');
}


Destruír o Token: Unha vez utilizado, é boa práctica invalidar o token.

unset($_SESSION['csrf_token']);




Exercicios propostos