PHP: Cookies e Sessões Programação de Servidores Marx Gomes Van der Linden
Protocolo HTTP O protocolo HTTP não tem conceito de sessões. Modelo simples de Requisição e Resposta. http://marx.vanderlinden.com.br/ 2
Protocolo HTTP Tipicamente, vários usuários estão acessando o servidor web ao mesmo tempo. HTTP não define uma maneira direta de se rastrear cada usuário e dar continuidade individual às atividades de requisições anteriores. http://marx.vanderlinden.com.br/ 3
Cookies Um Cookie é um arquivo de texto que pode ser criado pelo navegador, a pedido do servidor web. Cada cookie tem um conjunto de variáveis: nome=valor Todo cookie é necessariamente associado ao um site (ou domínio) que o criou e, teoricamente, não pode ser acessado por outros sites. http://marx.vanderlinden.com.br/ 4
Cookies O cookie é reenviado automaticamente ao servidor a cada nova visita à mesma página. Um cookie pode conter uma data de expiração (opcional) Default: Cookie é apagado ao se fechar o navegador. http://marx.vanderlinden.com.br/ 5
Cookies http://marx.vanderlinden.com.br/ 6
Cookies http://marx.vanderlinden.com.br/ 7
Cookies http://marx.vanderlinden.com.br/ 8
Usos de Cookies Armazenar itens no "carrinho de compras". Armazenar informações de autenticação. Guardar configurações do usuário. Permitir continuidade no uso de uma aplicação web. http://marx.vanderlinden.com.br/ 9
setcookie Para incluir na resposta HTTP uma solicitação para que o navegador crie um cookie, basta utilizar a função setcookie. Sintaxe (simplificada): setcookie($nome, $valor) Returna true em caso de sucesso, false em caso de erro. http://marx.vanderlinden.com.br/ 10
setcookie Deve ser usado antes de enviar qualquer dado pertencente ao corpo da mensagem! (inclusive espaços em branco). Não há garantias de que o navegador vai aceitar o cookie. http://marx.vanderlinden.com.br/ 11
pagina1.php <?php $b = setcookie('nome', 'Milhouse Van Houten');?> <html> <head> <title>cookies, página 1</title> </head> <body><?php if($b) echo "Cookie enviado com sucesso"; else echo "Erro ao enviar o cookie.";?></body> </html> http://marx.vanderlinden.com.br/ 12
Requisição HTTP GET /exemplo/pagina1.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; U; Linux i686; pt-br; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1 Accept: text/html,application/xhtml+xml,application/x ml;q=0.9,*/*;q=0.8 Accept-Language: pt-br,pt;q=0.8,enus;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 http://marx.vanderlinden.com.br/ 13 Connection: keep-alive
Resposta HTTP (Cabeçalho) HTTP/1.x 200 OK Date: Fri, 19 Sep 2008 21:01:36 GMT Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.3 with Suhosin-Patch X-Powered-By: PHP/5.2.4-2ubuntu5.3 Set-Cookie: nome=milhouse+van+houten Content-Length: 107 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html http://marx.vanderlinden.com.br/ 14
Saída <html> <head> <title>cookies, página 1</title> </head> <body>cookie enviado com sucesso</body> </html> http://marx.vanderlinden.com.br/ 15
$_COOKIE O interpretador PHP automaticamente organiza os cookies enviados pelo usuário ao servidor, através do array $_COOKIE. Formato: $_COOKIE[$nome] // retorna $valor http://marx.vanderlinden.com.br/ 16
pagina2.php <html> <head> <title>cookies, página 2</title> </head> <body> <?php if(isset($_cookie['nome'])) echo "Seu nome é $_COOKIE[nome]."; else echo "Eu não sei o seu nome.";?> </body></html> http://marx.vanderlinden.com.br/ 17
Requisição HTTP GET /exemplo/pagina2.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; U; Linux i686; pt-br; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1 Accept: text/html,application/xhtml+xml,application/x ml;q=0.9,*/*;q=0.8 Accept-Language: pt-br,pt;q=0.8,enus;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Cookie: nome=milhouse+van+houten Cache-Control: max-age=0 http://marx.vanderlinden.com.br/ 18
Resposta HTTP (Cabeçalho) HTTP/1.x 200 OK Date: Fri, 19 Sep 2008 21:07:02 GMT Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.3 with Suhosin-Patch X-Powered-By: PHP/5.2.4-2ubuntu5.3 Content-Length: 112 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html http://marx.vanderlinden.com.br/ 19
Saída <html> <head> <title>cookies, página 2</title> </head> <body> Seu nome é Milhouse Van Houten.</body></html> http://marx.vanderlinden.com.br/ 20
Cookies como arrays Para armazenar no cliente um cookie que será lido como um array, basta utilizar a notação de arrays. setcookie("valor[nome]", "Bill"); setcookie("valor[sobrenome]", "Gates"); setcookie("valor[empresa]", "Microsoft"); http://marx.vanderlinden.com.br/ 21
Cookies como arrays Depois, é possível usar o resultado do cookie recebido de volta como um array comum. if (isset($_cookie['valor'])) { foreach ( $_COOKIE['valor'] as $indice => $valor ) echo "$indice: $valor <br>\n"; } nome: Bill <br> sobrenome: Gates <br> empresa: Microsoft <br> http://marx.vanderlinden.com.br/ 22
Tempo de expiração Para evitar que o cookie seja excluído quando o navegador for fechado, é necessário especificar um tempo de expiração. Sintaxe completa: setcookie($nome, $valor, [$dataexpira], [$caminho], [$domínio]) Se $dataexpira não for especificado ou igual a 0, será excluído quando se fechar o navegador http://marx.vanderlinden.com.br/ 23
Tempo de expiração Cookie que expira em 1 hora: setcookie( 'login','milhouse', time() + 60*60 ); Cookie que expira em 1 dia: setcookie( 'login','krusty', time() + 60*60*24 ); Cookie que expira do dia 12 de outubro de 2010 setcookie( 'login','flanders', mktime(12,0,0, 10,12,2010) ); http://marx.vanderlinden.com.br/ 24
Diretório de aplicação do Cookie O terceiro parâmetro de setcookie serve para especificar a partir de que diretório, na estrutura de arquivos do servidor web, o cookie deve ser aplicado. Padrão: apenas diretório atual '/' Domínio inteiro http://marx.vanderlinden.com.br/ 25
Diretório de aplicação do Cookie Cookie válido para todo o domínio setcookie('login','burns', 0, '/' ); www.exemplo.com www.exemplo.com/dir1/springfield Cookie válido para um diretório setcookie('login','barney', time()+60*60, '/moe' ); www.exemplo.com/moe www.exemplo.com/moe/tavern http://marx.vanderlinden.com.br/ 26
Domínio de aplicação do Cookie Por padrão os cookies só são enviados para sites que tenham exatamente o mesmo domínio (incluindo subdomínio) www.exemplo.com meusite.exemplo.com O quarto parâmetro indica para que partes do domínio da URL o cookie deverá ser enviado. Não é possível especificar um domínio diferente daquele do site que registra o cookie! http://marx.vanderlinden.com.br/ 27
Domínio de aplicação do Cookie Cookie válido para todo o domínio setcookie('login','burns', 0, '/', '.exemplo.com' ); www.exemplo.com www.exemplo.com/dir1/springfield meusite.exemplo.com/shelbyville http://marx.vanderlinden.com.br/ 28
Excluindo um cookie Para excluir um cookie, basta passar um novo cookie com exatamente os mesmos parâmetros já passados, mas valor igual à string vazia. Criando: setcookie('login','burns', 0, '/' ); Excluindo: setcookie('login','', 0, '/' ); http://marx.vanderlinden.com.br/ 29
Características dos Cookies Todas as informações ficam armazenadas no cliente. O servidor não tem um controle preciso de que cookies estão armazenados para cada usuário. Todas os dados precisam ser repassados novamente a cada requisição HTTP feita pelo cliente. Cookies podem ser desativados, excluídos e modificados pelo cliente. http://marx.vanderlinden.com.br/ 30
Sessões PHP fornece um mecanismo de sessões. Quase todos os dados ficam armazenados no servidor. http://marx.vanderlinden.com.br/ 31
Sessões Quando a sessão inicia, o servidor gera um ID, que é uma string alfanumérica aleatória única (PHPSESSID) para identificar o cliente. O cliente armazena a ID como um cookie. Em todas as requisições seguintes, o cliente envia ao servidor apenas o cookie referente ao seu ID. A partir dos IDs, o servidor identifica e diferencia cada cliente. http://marx.vanderlinden.com.br/ 32
session_start() Para iniciar (ou continuar) uma sessão, basta usar a função session_start Sintaxe: session_start() Deve ser usado antes de qualquer saída do corpo da mensagem Sempre returna true http://marx.vanderlinden.com.br/ 33
$_SESSION Para ler e configurar variáveis de sessões, utiliza-se o array $_SESSION. Não há análogo em sessões à função setcookie. http://marx.vanderlinden.com.br/ 34
exemplo.php <?php session_start();?> <html> <head> <title>sessões</title> </head> <body> <?php if(!isset($_session['visitas'])) $_SESSION['visitas'] = 0;?> Esta é a sua visita número <?php echo $_SESSION['visitas']++?>. </body> </html> http://marx.vanderlinden.com.br/ 35
1a Requisição HTTP GET /delme/exemplo.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; U; Linux i686; pt-br; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1 Accept: text/html,application/xhtml+xml,application/x ml;q=0.9,*/*;q=0.8 Accept-Language: pt-br,pt;q=0.8,enus;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 http://marx.vanderlinden.com.br/ 36 Connection: keep-alive
1a Resposta HTTP (Cabeçalho) HTTP/1.x 200 OK Date: Fri, 19 Sep 2008 22:17:44 GMT Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.3 with Suhosin-Patch X-Powered-By: PHP/5.2.4-2ubuntu5.3 Set-Cookie: PHPSESSID=c7abd60716ef5c9df79f3788767aaec5; path=/ Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, mustrevalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 110 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html http://marx.vanderlinden.com.br/ 37
2a Requisição HTTP GET /delme/exemplo.php HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; U; Linux i686; pt- BR; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1 Accept: text/html,application/xhtml+xml,application/xml; q=0.9,*/*;q=0.8 Accept-Language: pt-br,pt;q=0.8,enus;q=0.5,en;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Cookie: PHPSESSID=c7abd60716ef5c9df79f3788767aaec5 http://marx.vanderlinden.com.br/ 38 Cache-Control: max-age=0
2a Resposta HTTP HTTP/1.x 200 OK Date: Fri, 19 Sep 2008 22:19:46 GMT Server: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.3 with Suhosin-Patch X-Powered-By: PHP/5.2.4-2ubuntu5.3 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, mustrevalidate, post-check=0, pre-check=0 Pragma: no-cache Content-Length: 110 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html http://marx.vanderlinden.com.br/ 39
session_set_cookie_params É possível configurar os parâmetros do cookie usado para armazenar o ID da sessão. Sintaxe: session_set_cookie_params( $dataexpira, [$caminho], [$domínio]) A sintaxe dos parâmetros é similar às da função setcookie. http://marx.vanderlinden.com.br/ 40
session_name A função session_name muda o nome do cookie que identifica o código da sessão. Deve ser chamado antes de session_start. Sintaxe: session_name($novonome) Return true em caso de sucesso; false em erro. http://marx.vanderlinden.com.br/ 41
session_id Sintaxe: session_id() Retorna o ID da seção atual, ou '', caso não haja sessão aberta. http://marx.vanderlinden.com.br/ 42
session_regenerate_id Sintaxe: session_regenerate_id() Gera um novo ID para a sessão atual. Envia uma novo requisição de Cookie ao cliente, sem quebrar a sessão. Precisa ser chamado antes de qualquer saída no corpo da resposta HTTP. Return true em caso de sucesso; false em erro. http://marx.vanderlinden.com.br/ 43
Configurando sessões Por padrão: Uma sessão continua ativa caso seja acessada pelo usuário ao menos 1 vez a cada 24 minutos. Sessões não servem para armazenar dados permanentes! Cada vez que session_start é chamada, há uma probabilidade de 1% de que o PHP vai varrer todas as sessões ativas, e excluir as que expiraram. http://marx.vanderlinden.com.br/ 44
ini_set A função ini_set serve para mudar temporariamente alguma configuração do PHP. Sintaxe: ini_set($variável, $novovalor) Return true em caso de sucesso; false em erro. http://marx.vanderlinden.com.br/ 45
session.gc_maxlifetime Especifica o tempo (em segundos) máximo que uma sessão deve durar, esperando pelo usuário. Padrão: 1440 (24 minutos). Deve ser modificada antes de session_start() ini_set('session.gc_maxlifetime', 600); session_start( ); http://marx.vanderlinden.com.br/ 46
session.gc_probability Especifica a probabilidade (em %) de que o PHP vai fazer a verificação e limpeza das sessões expiradas, a cada chamada de session_start. Padrão: 1 Também deve ser modificada antes de session_start ini_set('session.gc_probability', 100); session_start( ); http://marx.vanderlinden.com.br/ 47
Segurança Problema de segurança: A ID da sessão pode ser interceptada por alguém que esteja monitorando a rede. Se outra pessoa usar a mesma ID para fazer requisições ao servidor, pode fazer se passar por outro usuário. http://marx.vanderlinden.com.br/ 48
Funções de Hash http://marx.vanderlinden.com.br/ 49
Funções de Hash PHP implementa as funções de hash mais comuns: md5($string) sha1($string) hash($algoritmo, $string) (Função genérica que implementa vários algoritmos) http://marx.vanderlinden.com.br/ 50
md5 echo md5("the book is on the table"), " <br>\n"; echo md5("the book is on the table."), " <br>\n"; 0c29bf0f928decfbf91070fa4affb0c4 <br> 1f683fe1cd7977cdd056ddc25d6bd8f8 <br> http://marx.vanderlinden.com.br/ 51
$_SERVER O array $_SERVER contém informações fornecidas pelo servidor web, como cabeçalhos, caminhos de arquivo e configurações. Os índices do array são fixos e seus valores não podem ser modificados. http://marx.vanderlinden.com.br/ 52
$_SERVER Exemplos: 'PHP_SELF' Nome do script atual 'SERVER_ADDR' Endereço IP do servidor 'SERVER_NAME' Nome do servidor 'HTTP_USER_AGENT' Configurações do cliente 'REMOTE_ADDR' Endereço IP do cliente http://marx.vanderlinden.com.br/ 53
$_SERVER $keys = array( 'PHP_SELF', 'SERVER_ADDR', 'SERVER_NAME', 'HTTP_USER_AGENT', 'REMOTE_ADDR', ); foreach($keys as $k) echo "$k: $_SERVER[$k]<br>\n"; PHP_SELF: /exemplo/exemplo.php<br> SERVER_ADDR: 127.0.0.1<br> SERVER_NAME: localhost<br> HTTP_USER_AGENT: Mozilla/5.0 (X11; U; Linux i686; pt-br; rv:1.9.0.1) Gecko/2008072820 Firefox/3.0.1<br> REMOTE_ADDR: 127.0.0.1<br> http://marx.vanderlinden.com.br/ 54
Sessão Segura (1/2) <?php session_start(); $md5 = md5( $_SERVER['HTTP_USER_AGENT']. $_SERVER['REMOTE_ADDR'] ); if (!isset($_session['md5'])) { session_regenerate_id(); $_SESSION['md5'] = $md5; $msg = "Bem-vindo!<br>\n"; } if ($_SESSION['md5']!= $md5) { $_SESSION = array(); $_SESSION['md5'] = $md5; $msg = "Erro! Por favor, faça o login novamente.<br>\n"; } else $msg.= "Continuando...";?> http://marx.vanderlinden.com.br/ 55
Sessão Segura <html> <head><title>sessões</title></head> <body> <?php echo $msg?> </body> </html> http://marx.vanderlinden.com.br/ 56
Saída Primeira execução: OK!<br> Continuando sessão Execuções seguintes: Continuando sessão Tentativa de ataque: Erro! Por favor, faça o login novamente. http://marx.vanderlinden.com.br/ 57