downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

session_cache_expire> <session_pgsql_status
[edit] Last updated: Mon, 01 Nov 2010

view this page in

CXLII. Funções de manpulação de Sessões

Introdução

O suporte a sessões no PHP consiste em uma maneira de preservar certos dados atráves dos acessos subsequentes. Isto permite a você fazer aplicações mais personalizadas e melhorar a aparência do seu web site

Um visitante acessando o seu web site ganha um identificados único, o assim chamado id de sessão. Este é salvo em um cookie do lado do usuário ou propagado via URL.

O suporte a sessão permite a você registrar um numero arbritario de variáveis que serão preservadas entre as requisições. Quando um visitante acessar o seu site, o PHP irá conferir automaticamente (se session.auto_start estiver definido como 1) ou quando você pedir (explicitamente atráves de session_start() ou implicitamente atráves de session_register()) quando um id de sessão especifico for enviado com a requisição. Se este for o caso, o ambiente anteriormente salvo é recriado.

Cuidado

Se você ativar session.auto_start então você não poderá colocar objetos em suas sessões já que a definição deve ser carregada antes de começar a sessão para poder recriar os objetos da sua sessão.

Todas as variáveis são serializadas depois das solicitações terminarem. Variáveis registradas as quais não estejam definidas são marcadas como sendo não definidas. Nos acessos subsequentes, estas não são definidas pelo modulo da sessão a menos que o usuário defina elas posteriormente.

Atenção

Alguns tipos de dados não podem ser serializados e assim guardados em sessões. Isso inclui variáveis de resource(recursos) ou objetos com referencias circulares (ex. objetos que passam uma referencia de sí mesmo para outro objeto).

Nota: A manipulação de sessões foi adicionado no PHP 4.0.

Nota: Por favor note que ao trabalhar com sessões que um registro da sessão não é criado até que a variável seja registrada usando a função session_register() ou pela adição de uma nova chave a array superglobal $_SESSION. Isto é verdadeiro não importando se uma sessão foi iniciada usando a função session_start().

Sessões e segurança

Links externos: Session fixation

O módulo das sessões não pode garantir que a informação que você guarda em uma sesão será visto somente pelo usuário que criou a sessão. Você precisa tomar medidas adicionais de segurança para proteger ativamente a integridade da sessão, dependendo do valor dos dados.

Meça a importancia dos dados carregados pelas suas sessões e tome medidas adicionais de proteção -- isto normalmente vem com um preço, menos convêniencia para o usuário. Por exemplo, se você quiser proteger os usuários de taticas simples de engenharia social, você deve ativar session.use_only_cookies. Neste caso, os cookies devem estar ativados incondicionalmente do lado do usuário ou as sessões não irão funcionar.

Existem várias maneiras de vazar um id de uma sessão para terceiros. Um id de sessão vazado permite a terceiros acessar a todos os recursos que estão associados ao id especifico. Primeiro, URL´s carregando ids de sessão. Se você criar um link com um site externo, a URL inclusa no id de sessão deve ser guardada nos logs de referência do site externo. Segundo, um ataque mais ativo pode escutar ao seu tráfego de rede. Se ele não for criptografado, os ids de sessão irão passar como texto simples pela sua rede. A solução aqui é implementar SSL em seu servidor e tornar obrigatório para os seus usuários.

Dependências

Nenhuma biblioteca externa é necessária para compilar esta extensão.

Nota: Opcionalmente você pode usar alocação de memória compartilhada (mm), desenvolvida por Ralf S. Engelschall, para salvar a sessão. Você terá que baixar mm e instala-lo. esta opção não esta disponível para plataformas windows. Note que o módulo de sessões para o mm não garante que acessos concorrentes a mesma sessão sejam travados propriamente. Pode ser mais apropriado usar um sistema de arquivos baseado em memória compartilhada (como tmpfs em Solaris/Linux, ou /dev/md em BSD) para salvar sessões em arquivos, por que eles são propriamente travados. Os dados das sessões são salvos na memória então se o servidor for reiniciado os dados são excluídos.

Instalação

Suporte a sessões está habilitado no PHP por definição. Se você não gostaria de construir o seu PHP sem esse suporte, você especificaria a opção --disable-session para configurar. Para utilizar uma alocação de memória dividida (mm) para armazenamento de sessão configure o PHP com --with-mm[=DIR] .

A versão para Windows do PHP tem suporte embutido para esta extensão. Você não precisa carregar nenhuma extensão adicional para utilizar essas funções.

Nota: Por definição, todos os dados relaciondos uma uma sessão em particular serão guardados num arquivo no diretório especificado pela opção session.save_path INI . Um arquivo para cada sessão (apesar de quaisquer dados estarem associados com essa sessão) será criada. Isto é devido ao fato de que uma sessão é aberta (um aquivo é criado) mas até então nenhum dado é escrito nesse arquivo. Note que este comportamento é um efeito colateral da limitação do traalho com o arquivo de sistema e é possível que um manipulador de sessão customizado(tal como é usado em banco de dados) não manterá registro de sessões que não guardaram nenhum dado.

Configurações em execução

O comportamento dessas funções podem ser modificado pelas configurações do php.ini.

Tabela 1. Opções de configuração da sessão

NomePadrãoModificávelMudanças
session.save_path"/tmp"PHP_INI_ALL 
session.name"PHPSESSID"PHP_INI_ALL 
session.save_handler"files"PHP_INI_ALL 
session.auto_start"0"PHP_INI_ALL 
session.gc_probability"1"PHP_INI_ALL 
session.gc_divisor"100"PHP_INI_ALL 
session.gc_maxlifetime"1440"PHP_INI_ALL 
session.serialize_handler"php"PHP_INI_ALL 
session.cookie_lifetime"0"PHP_INI_ALL 
session.cookie_path"/"PHP_INI_ALL 
session.cookie_domain""PHP_INI_ALL 
session.cookie_secure""PHP_INI_ALLAvailable since PHP 4.0.4.
session.cookie_httponly""PHP_INI_ALLAvailable since PHP 5.2.0.
session.use_cookies"1"PHP_INI_ALL 
session.use_only_cookies"0"PHP_INI_ALLDisponível desde o PHP 4.3.0
session.referer_check""PHP_INI_ALL 
session.entropy_file""PHP_INI_ALL 
session.entropy_length"0"PHP_INI_ALL 
session.cache_limiter"nocache"PHP_INI_ALL 
session.cache_expire"180"PHP_INI_ALL 
session.use_trans_sid"0"PHP_INI_ALLPHP_INI_ALL no PHP <= 4.2.3. PHP_INI_PERDIR no PHP < 5. Disponível desde o PHP 4.0.3.
session.bug_compat_42"1"PHP_INI_ALLDisponível desde o PHP 4.3.0
session.bug_compat_warn"1"PHP_INI_ALLDisponível desde o PHP 4.3.0
session.hash_function"0"PHP_INI_ALLDisponível desde o PHP 5.0.0
session.hash_bits_per_character"4"PHP_INI_ALLDisponível desde o PHP 5.0.0
url_rewriter.tags"a=href,area=href,frame=src,form=,fieldset="PHP_INI_ALLDisponível desde o PHP 4.0.4.
Para mais detalhes e definições das constantes PHP_INI_*, veja a documentação de ini_set().

O sistema de gerenciamento de sessões suporta um número de opções de configuração que você pode colocar em seu arquivo php.ini. Nós daremos um breve resumo.

session.save_handler string

session.save_handler define o nome do manipulador que é usado para guardar e devolver dados associados com a sessão. Padrão inicial files. Veja também session_set_save_handler().

session.save_path string

session.save_path define o argumento que é passado para o manipulador de salvação. Se você escolher o manipulador de ausência de arquivo, este é o local onde os arquivos serão criados. Padrão /tmp. Veja também session_save_path().

Há um argumento N opcional para esta dietiva que determina o número de níveis de diretório que seus arquivos de sessão serão extendidos. Por exemplo, definindo para '5;/tmp' pode levar a criação de um arquivo de sessão e localização como /tmp/4/b/1/e/3/sess_4b1e384ad74619bd212e236e52a5a174If . Para fazer uso do N você deve criar todos estes diretórios antes de usar. Um pequeno script shell existe em ext/session para fazer isto, ele é chamado mod_files.sh. Também note se N é usada e maior do que and greater than 0 então a "automatic garbage collection" não será executada, veja uma cópia do php.ini para mais informação. Veja, se você usa N if you use N, be certifique-se de cercar session.save_path com "aspas" porque o separador (;) é também usado para comentátios no php.ini.

Atenção

Se você deixar isto definido num diretório de leitura público, tal como /tmp (o padrão), outros usuários no servidor poderão raptar sessõoes pegando a lista de arquivos nesse diretório.

Nota: Antes do PHP 4.3.6 os usuários de Windows tem que mudar esta variável para fazer funções de sessão no PHP. Certifique-se de especifica um caminho válido, ex.: c:/temp.

session.name string

session.name especifíca o nome da sessão que é usada como um nome de cookie. Ele somente conteria caracteres alfanuméricos. Padrão inicial PHPSESSID. Veja também session_name().

session.auto_start boolean

session.auto_start especifíca se o módulo da sessão começou uma sessão automaticamente num pedido no início. Definido iniciamente em 0 (desabilitado).

session.serialize_handler string

session.serialize_handler define o nome do manipulador que é usado para publicar/despublicar dados em série (serialize/deserialize). Atualmente, como um formato interno no PHP (nome php) e WDDX é suportado (nome wddx). WDDX está apenas disponível, se o PHP está compilado com suporte a WDDX . Definição inicial php.

session.gc_probability integer

session.gc_probability em conjunto com session.gc_divisor é usado para gerenciar a probabilidade que o gc (coletor de lixo) seja iniciado. O padrão é 1. Veja session.gc_divisor para detalhes.

session.gc_divisor integer

session.gc_divisor em conjunto com session.gc_probability define a probabilidade que o processo do gc (coletor de lixo) seja iniciado na inicialização de cada sessão. A propabilidade é cauculada usando gc_probability/gc_divisor, ex. 1/100 indica que existe 1% de chance que o processo GC comece em cada requisição.. O padrão para session.gc_divisor é 100.

session.gc_maxlifetime integer

session.gc_maxlifetime especifíca o número de segundos após os dados terem sido considerados como lixo ('garbage') e limpados. Isso ocorre durante o início da sessão Desde o PHP 4.2.3 é usado mtime (data de modificação) ao invés de atime. Assim você não terá problemas em sistemas de arquivos onde atime não esteja disponível.

Nota: Se scripts diferentes tem valores diferentes para session.gc_maxlifetime mas compartilham o mesmo lugar para guardar os dados da sessão então o script com o menor valor estara limpando os dados. Neste caso, use esta diretiva em conjunto com session.save_path.

Nota: Se você está usando o file-based session handler como padrão, seu sistema de arquivos deve manter registrado quantidade de acessos (atime). Windows FAT dessa forma não faz, então você terá que sugerir outro modo para manipular a coleção de lixo de sua sessão se você está num sistema FAT ou quaisquer outros fs onde quantidade de acessos (atime tracking) não está disponível.

session.referer_check string

session.referer_check contém a substring que você quer checar para cada referenciador (Referer) de HTTP. Se o referenciador foi enviado pelo cliente e a sustring não foi encontrada, a id de sessão embutida será marcada como inválida. O padrão é uma string vazia.

session.entropy_file string

session.entropy_file diz o caminho para um recurso externo (arquivo) que será usado como uma fonte de desordem no processo de criação da id da sessão. Exemplos são /dev/random or /dev/urandom que são disponíveis em muitos sistemas UNIX.

session.entropy_length integer

session.entropy_length especifíca o número de bytes que serão lidos do arquivo especificado acima. Definido inicialmente como 0 (desabilitado).

session.use_cookies boolean

session.use_cookies especifica se módulo utilizará cookies para guardar a id da sessão no lado do cliente. O padrão é 1 (habilitado).

session.use_only_cookies boolean

session.use_only_cookies especifica que o módulo usará apenas cookies para guardar a id no lado do cliente. Habilitando esta configuração previne ataques envolvendo passagem de ids de sessão nas URLs. Esta configuração foi adicionada no PHP 4.3.0.

session.cookie_lifetime integer

session.cookie_lifetime especifica o tempo de vida do cookie em segundos que é enviado para o browser. O valor 0 significa "até o browser ser fechado." O padrão é 0. Veja também session_get_cookie_params() e session_set_cookie_params(). Já que o cookie é retornado pelo browser, ele não é prolongado para todo o tempo necessário. Ele deve ser enviado manualmente usando setcookie().

session.cookie_path string

session.cookie_path especifica o caminho para definir em session_cookie. O padrão é /. Veja também session_get_cookie_params() e session_set_cookie_params().

session.cookie_domain string

session.cookie_domain especifica o domínio para definir no cookie de sessão. O padrão é nenhum significando o nome do servidor que gerou o cookie de arcordo com a especificação dos cookies. Veja também session_get_cookie_params() e session_set_cookie_params().

session.cookie_secure boolean

session.cookie_secure especifíca se o cookie seria apenas enviado sob conexões seguras. O padrão é off. Esta definição foi adicionada no PHP 4.0.4. Veja também session_get_cookie_params() e session_set_cookie_params().

session.cookie_httponly boolean

marca o cookie para ser acessível apenas atráves do protocolo HTTP. Isto significa que o cookie não será acessível por linguagens de script, como o JavaScript. Esta definição pode efetivamente reduzir o roubo de identidade atráves de ataques XSS (mesmo não sendo suportado por todos os browsers).

session.cache_limiter string

session.cache_limiter especifíca o método de controle do cache para usar em páginas de sessão (none/nocache/private/private_no_expire/public). O padrão é nocache. Veja também session_cache_limiter().

session.cache_expire integer

session.cache_expire especifíca o time-to-live (termo de internet - um campo do ip header que indica o tamanho do pacote que seria permitido durar antes de ser descartado) para páginas de sessão em minutos, este não tem efeito para nocache limiter. O padrão é 180. Veja também session_cache_expire().

session.use_trans_sid boolean

session.use_trans_sid se suporte a sid transparente está habilitado ou não. O padrão é 0 (desabilitado).

Nota: Para PHP 4.1.2 ou inferior, ele só é habilitado se fizer a opção na compilação com --enable-trans-sid. A partir do PHP 4.2.0, está sempre compilado.

Gerenciamentode sessões baseadas na URL tem riscos de segurança adicionais comparados ao gerenciamento baseado em cookies. Usuários podem enviar uma URL que contenha uma ID de sessão ativa para seus amigos por e-mail ou usuários pode salvar uma URL que contenha uma ID de sessão para seus bookmarks e acessar seu site com a mesma ID de sessão sempre, por exemplo.

session.bug_compat_42 boolean

Versões do PHP 4.2.3 and ou inferior não tem documentado atributo/bug que te mostre como inicializar uma variável de sessão no escopo global, embora register_globals está desabilitado. PHP 4.3.0 e mais novos avisarão você,se este atributo está sendo usado, e se session.bug_compat_warn está também habilitado. Este funcionamento/bug pode ser desativado se desativando esta diretiva.

session.bug_compat_warn boolean

Versões do PHP 4.2.0 e inferiores não tem documentados atributo/bug te indique como começar uma variável de sessão no escopo global, embora register_globals esteja desabilitado. PHP 4.3.0 e posteriores avisarão a você, se este atributo está sendo usado habilitado em ambos session.bug_compat_42 and session.bug_compat_warn.

session.hash_function integer

session.hash_function permite a você especificar o algoritimo de hash usado para gerar os IDs de sessão. '0' indica MD5 (128 bits) e '1' indica SHA-1 (160 bits).

Nota: Isto foi introduzido no PHP 5.

session.hash_bits_per_character integer

session.hash_bits_per_character permite a você definir quantos bits são guardaddos em cada caractere ao converter os dados binários de hash para algo que possa ser legível. Os valores possíveis são '4' (0-9, a-f), '5' (0-9, a-v), e '6' (0-9, a-z, A-Z, "-", ",").

Nota: Isto foi introduzido no PHP 5.

url_rewriter.tags string

url_rewriter.tags epecifíca quais tags HTML são reescritas para incluir a id de sessão se o suporte a sid transparente está habilitado. O padrão é a=href,area=href,frame=src,input=src,form=fakeentry,fieldset=

Nota: Se você quer conformidade XHTML, remova a entrada form e utilize as tags <fieldset> em volta dos campos de formulário.

As definições de configuraçãotrack_vars e register_globals influenciam como as variáveis de sessão são guardadas e restauradas.

Nota: No PHP 4.0.3, track_vars está sempre ligada.

Tipos Resource

Esta extensão não possui nenhum tipo resource.

Constantes pré-definidas

As contantes abaixo são definidas por esta extensão e somente estarão disponíveis quando a extensão foi compilada com o PHP ou carregada dinamicamente durante a execução.

SID (string)

Constantes contendo o nome da sessão e o ID da sessão na forma de "name=ID" ou uma string vazia no caso de o ID não tenha sido apropriadamente salvo em um cookie de seção.

Exemplos

Nota: A partir do PHP 4.1.0, $_SESSION esta disponível como uma variável global como $_POST, $_GET, $_REQUEST e assim por diante. Diferentemente de $HTTP_SESSION_VARS, $_SESSION é sempre global. Entretanto, você não precisa usar a palavra global para $_SESSION. por favor note que esta documentação foi modifcada para usar $_SESSION em todos os lugares. Você pode substituir $HTTP_SESSION_VARS por $_SESSION, se você prefirir. Também note que você precisa começar a sua sessão usando session_start() antes que $_SESSION esteja disponível.

As chaves para a array associativa $_SESSION estão sujeitas ao mesmas limitações que as os nomes de variáveis regulares do PHP, ex elas não podem começar com um numero e devem começar com uma letra ou sublinhado;. Para maiores detalhes veja a sessão sobre variaveis neste manual.

Se register_globals estiver desativado, apenas membros da matriz associativa global $_SESSION podem ser registrados como variáveis de sessão. As variavéis de sessão restauradas apenas estarão disponíveis na array $_SESSION.

O uso de $_SESSION (ou $HTTP_SESSION_VARS com PHP 4.0.6 ou anterior) é recomendado para melhor segurança e facilidade de leitura do código. Com $_SESSION, não há necessidade de usar as funções session_register(), session_unregister(), session_is_registered(). Variáveis de sessão são acessíveis como qualquer outra variável.

Exemplo 1. Registrando uma variável com $_SESSION.

<?php
session_start
();
// Use $HTTP_SESSION_VARS with PHP 4.0.6 or less
if (!isset($_SESSION['count'])) {
   
$_SESSION['count'] = 0;
} else {
   
$_SESSION['count']++;
}
?>

Exemplo 2. Desregistrando uma variável com $_SESSION e register_globals desabilitado.

<?php
session_start
();
// Use $HTTP_SESSION_VARS with PHP 4.0.6 or less
unset($_SESSION['count']);
?>

Cuidado

NÃO desregistre toda a $_SESSION com unset($_SESSION) já que isso irá desativar o registro de variáveis de sessão atráves da superglobal $_SESSION.

Atenção

Você não pode usar referencias em variáveis de sessão já que não existe uma maneira de restaurar uma referencia a outra variável.

Se register_globals estiver ativada, então cada variável global pode ser registrada como uma variável de sessão. Após o reinicio da sessão, estas variáveis serão restauradas a suas variáveis globais correspondentes. Já que o PHP deve saber quais variáveis globais devem ser registradas como variáveis de sessão, o usuário precisa registrar as variáveis com a função session_register(). Você pode evitar isso simplesmente definindo entradas em $_SESSION.

Cuidado

Antes do PHP 4.3, se você estiver usando $_SESSION e voc desabilitou register_globals, não use session_register(), session_is_registered() ou session_unregister(). Desabilitar register_globals é recomendado por motivo de segurança e performance.

Se register_globals estiver ativada, então as variáveis globais e as entradas em $_SESSION irão automaticamente referenciar os mesmos valores que estejam registrados na instancia da sessão anterior. Entretanto, se a variável for registrada por $_SESSION então a variável global estará disponível a partir da proxima requisição.

Existe um defeito no PHP 4.2.3 e anterior. Se você registrar uma nova variável de sessão usando session_register(), a entrada no escopo global e a entrada em $_SESSION não irão se referir ao mesmo valor até o próximo session_start(). Ex: uma modificação na variável global recém registrada não será refletida pela entrada em $_SESSION. Isto foi corrigido no PHP 4.3.

Passando o ID de Sessão

Existem dois metodos para a propagação do id de sessão:

  • Cookies

  • Parâmetro de URL

O módulo de sessão suporta ambos os métodos. Cookies são melhores, mas como eles nem sempre estão disponíveis, nós também provemos um caminho alternativo. O segundo metodo embute o id de sessão diretamente nas URLs.

O PHP é capaz de transformar os links transparentemente. A menos que você esteja usando o PHP 4.2 ou posterior, você precisa ativar isso manualmente ao compilar o PHP. No Unix, passe --enable-trans-sid para o configure. Se esta opção de compilação e a opção em tempo execução session.use_trans_sid estiverem ativadas, URIs relativas serão modificadas para conter o id de sessão automaticamente.

Nota: A diretiva arg_separator.output php.ini permite a você personalizar o separador de argumentos. Para estar em completa conformidade com XHTML, especifique &amp; aqui.

Alternativamente, você pode usar a constante SID a qual é definida se uma sessão é iniciada. Se o cliente não enviou um cookie de sessão apropriado, ela tem a forma session_name=session_id. Se não, ela expande para uma string vazia. Assim, você pode coloca-la incondicionalmente em URLs.

O exemplo a seguir mostra como registrar uma variável, e como criar um link corretamente para outra pagina usando SID.

Exemplo 3. Contando o número de visitas de um unico usuário

<?php
if (!session_is_registered('count')) {
   
session_register('count');
   
$count = 1;
} else {
   
$count++;
}
?>

<p>
Hello visitor, you have seen this page <?php echo $count; ?> times.
</p>

<p>
To continue, <a href="nextpage.php?<?php echo strip_tags(SID); ?>">click
here</a>.
</p>

A função strip_tags() é usada ao mostrar o SID para previnir ataques relacionados a XSS.

Mostrar o SID, como mostrado acima, não é necessário se --enable-trans-sid foi usado para compilar o PHP.

Nota: É assumido para URLs não relativas que apontem para sites externos e assim não é adicionado o SID, já que seria um risco de segurança vazar o SID para um servidor diferente.

Manipuladores de sessões personalizados

Para implementar as sessões em banco de dados, ou qualquer outreo metodo de armazenamento, você precisara usar session_set_save_handler() para criar um conhunto de funções de armazenamento.

Índice
session_cache_expire -- Retorna o prazo do cache atual
session_cache_limiter -- Obtém e/ou define o limitador do cache atual
session_commit -- Sinônimo de session_write_close()
session_decode -- Decifra dado de sessão de uma string
session_destroy -- Destroi todos os dados registrados em uma sessão
session_encode --  Codifica os dados da sessão atual como uma string
session_get_cookie_params --  Obtém os parâmetros do cookie da sessão
session_id -- Obtém e/ou define o id de sessão atual
session_is_registered --  Descobre se uma variável global está registrada numa sessão.
session_module_name -- Obtém e/ou define o módulo da sessão atual
session_name -- Obtém e/ou define o nome da sessão atual
session_regenerate_id --  Atualiza o id da seção atual com um novo gerado
session_register --  Registrar uma ou mais variáveis globais na sessão atual
session_save_path -- Obtém e/ou define o save path da sessão atual
session_set_cookie_params --  Define os parâmetros do cookie de sessão
session_set_save_handler --  Define a sequência de funções de armazenamento
session_start -- Inicia dados de sessão
session_unregister --  Desregistra uma variável global da sessão atual
session_unset --  Libera todas as variáveis de sessão
session_write_close -- Escreve dados de sessão e termina a sessão


session_cache_expire> <session_pgsql_status
[edit] Last updated: Mon, 01 Nov 2010
 
add a note add a note User Contributed Notes Funções de manpulação de Sessões
Sam Yong - hellclanner at live dot com 27-Jul-2011 02:01
The following has been tested true in PHP 5.3.5.

Setting the session variables after the execution of the script i.e. in __destruct function, will not work.

<?php

class Example{

    function
__destruct(){
       
$_SESSION['test'] = true;
       
session_write_close();
    }

}

?>

The above example will write nothing into the temporary session file, as I observed through a custom Session Save Handler.
jitchavan at gmail dot com 01-Apr-2011 06:43
IE issue :-

when form target set to iframe source and after posting form content you are setting session variables,
In this scenario if parent page having image src blank then session values set in iframe action page will be LOST surprisingly in IE ONLY.Solution is quite simple don't keep Image src blank.
ted at tedmurph dot com 07-Oct-2010 05:34
I was having problems with $_SESSION information not being written or being lost in a seemingly random way.  There was a Location: call being made deep in a Zend OAuth module, I am using an IIS server with PHP as a CGI, etc.

The answer was simply that you need to have the domain be consistent for sessions to work consistently.  In my case, I was switching back and forth between www.EXAMPLE.com:888 and EXAMPLE.com:888.  The unusual port, the hidden Location: call, the handoff with OAuth, etc all served to confuse me, but the intermitent error was caused by this simple goof of keeping the domain consistent.
hinom06 [at] hotmail.co.jp 29-Aug-2010 10:28
simple session test version 1.1

<?php
/* [EDIT by danbrown AT php DOT net:
   The author of this note named this
   file tmp.php in his/her tests. If
   you save it as a different name,
   simply update the links at the
   bottom to reflect the change.] */

error_reporting( E_ALL );
ini_set( 'display_errors', 1);
date_default_timezone_set('Asia/Tokyo');

//ini_set( 'session.save_path', '/tmp' ); // for debug purposes
  
session_start();

// check if session_id() exists.
/*
for example, if exists and session wont read, must send session.name as parameter in URL.

Some servers configurations may have problem to recognize PHPSESSID, even if transid value is 0 or 1. 
So, this test is usefull to identify any causes.

*/
if( session_id() == '' )
{
    echo
'session_id() empty';
}else{
    echo
session_id();
}
echo
'<hr>';

$sessPath   = ini_get('session.save_path');
$sessCookie = ini_get('session.cookie_path');
$sessName   = ini_get('session.name');
$sessVar    = 'foo';

echo
'<br>sessPath: ' . $sessPath;
echo
'<br>sessCookie: ' . $sessCookie;

echo
'<hr>';

if( !isset(
$_GET['p'] ) ){
   
// instantiate new session var
   
$_SESSION[$sessVar] = 'hello world';
}else{
    if(
$_GET['p'] == 1 ){

       
// printing session value and global cookie PHPSESSID
       
echo $sessVar . ': ';
        if( isset(
$_SESSION[$sessVar] ) ){
            echo
$_SESSION[$sessVar];
        }else{
            echo
'[not exists]';
        }

        echo
'<br>' . $sessName . ': ';

        if( isset(
$_COOKIE[$sessName] ) ){
        echo
$_COOKIE[$sessName];
        }else{
            if( isset(
$_REQUEST[$sessName] ) ){
            echo
$_REQUEST[$sessName];
            }else{
                if( isset(
$_SERVER['HTTP_COOKIE'] ) ){
                echo
$_SERVER['HTTP_COOKIE'];
                }else{
                echo
'problem, check your PHP settings';
                }
            }
        }

    }else{

       
// destroy session by unset() function
       
unset( $_SESSION[$sessVar] );

       
// check if was destroyed
       
if( !isset( $_SESSION[$sessVar] ) ){
            echo
'<br>';
            echo
$sessName . ' was "unseted"';
        }else{
            echo
'<br>';
            echo
$sessName . ' was not "unseted"';
        }

    }
}
?>
<hr>
<a href=tmp.php?p=1&<?php echo $sessName . '=' . session_id();?>>test 1 (printing session value)</a>
<br>
<a href=tmp.php?p=2&<?php echo $sessName . '=' . session_id();?>>test 2 (kill session)</a>
Trevor Brown 04-Aug-2010 08:17
A confirmation of behaviour, just in case this saves anyone else some time...

There is (potentially) a special case when session.gc_probability = 0 and session.gc_divisor = 0.  Depending on how they wanted to work their maths underneath, the coders *might* have opted to interpret 0/0 as 1 (which is sometimes assumed in certain maths proofs), but thankfully it seems they haven't.  With both values set to 0, the session code will follow the spirit of the directives and invoke the garbage collector with zero probability.  At least this is true with php 5.2.5 (which, to be certain, I inspected the source of).

To be safe, however, setting both to zero is *probably* not a good idea because usually 0/0 is undefined, so it could presumably mean anything (some arguments exist that claim 0/0 is equal to every fraction).  Wouldn't you rather know for sure what your probability was set to?  In other words, don't set gc_divisor = 0
Jeremy Speer 19-Feb-2010 12:14
When working on a project, I found a need to switch live sessions between two different pieces of software. The documentation to do this is scattered all around different sites, especially in comments sections rather than examples. One difficulty I encountered was the session save handler for one of the applications was set, whereas the other was not. Now, I didn't code in the function session_set_save_handler(), instead I utilize that once I'm done with the function (manually), however this function could easily be extended to include that functionality. Basically, it is only overriding the system's default session save handler. To overcome this after you have used getSessionData(), just call session_write_close(), session_set_save_handler() with the appropriate values, then re-run session_name(), session_id() and session_start() with their appropriate values. If you don't know the session id, it's the string located in $_COOKIE[session_name], or $_REQUEST[session_name] if you are using trans_sid. [note: use caution with trusting data from $_REQUEST, if at all possible, use $_GET or $_POST instead depending on the page].

<?php
function getSessionData ($session_name = 'PHPSESSID', $session_save_handler = 'files') {
   
$session_data = array();
   
# did we get told what the old session id was? we can't continue it without that info
   
if (array_key_exists($session_name, $_COOKIE)) {
       
# save current session id
       
$session_id = $_COOKIE[$session_name];
       
$old_session_id = session_id();
       
       
# write and close current session
       
session_write_close();
       
       
# grab old save handler, and switch to files
       
$old_session_save_handler = ini_get('session.save_handler');
       
ini_set('session.save_handler', $session_save_handler);
       
       
# now we can switch the session over, capturing the old session name
       
$old_session_name = session_name($session_name);
       
session_id($session_id);
       
session_start();
       
       
# get the desired session data
       
$session_data = $_SESSION;
       
       
# close this session, switch back to the original handler, then restart the old session
       
session_write_close();
       
ini_set('session.save_handler', $old_session_save_handler);
       
session_name($old_session_name);
       
session_id($old_session_id);
       
session_start();
    }
   
   
# now return the data we just retrieved
   
return $session_data;
}
?>
brfelipe08 at hotmail dot com 28-Aug-2009 06:26
If you need to use sessions, and some accents required for some Latin-based languages, you should encode your files in ISO-8859-1.
You will run into some problems if you try to use UTF-8 - with or without BOM -, and ANSI will not support accents.
ISO-8859-1 will both support sessions and the accents.
edA-qa at disemia dot com 08-May-2009 12:18
WARNING for Debian users.  Just to drive you completely crazy Debian does its own form of session management and will completely ignore all alterations to the values who do within your PHP script.

Debian sets up a <crontab /etc/cron.d/php5> which deletes all files, including those in subdirectories, which exceed the gc_maxlifetime specified in the <php.ini> file only.

That is, on Debian (and likely variants like Ubuntu) modifying the session expiration settings (like gc_maxlifetime) does *NOTHING*.  You *HAVE* to modify the global <php.ini>.  Not even a <.htaccess> file will help you.
edA-qa at disemia dot com 07-May-2009 05:14
Sessions may be deleted before the time limit you set in gc_maxlifetime.

If you have multiple pages on the same server, each using the session (the same or distinct named sessions, it doesn't matter), the *minimum* gc_maxlifetime of any of those scripts ends up being the effective lifetime of the session files.

This can also apply to the lifetime coming from a CLI invocation of a PHP script on that machine which happens to use the session.

This can be bothersome since even though you think all your pages include the same file which sets up the script, even a single PHP page which doesn't can invoke the GC and have the scripts deleted.

Thus, if you need to set a long gc_maxlifetime you are best doing this through the INI file or in a .htaccess file for the entire directory.
LaurentT 03-Dec-2008 02:51
For UNIX :

One might encounter some problems with sessions, having different sites on the same server : sessions would either merge if one is using more than one site at a time or crash if sites are owned by different system users. For instance :

www.example.com is stored in /home/site1/www
www.example.net is stored in /home/site2/www

Using both www.example.com and www.example.net would cause sessions to act weird.

If you're using PHP as an Apache module, you can easely use php_value in the http.conf to set a unique session.name depending on the site. If you're using suPHP though (PHP as CGI) you can't use php_value, though you can use suPHP_ConfigPath.

Here's an example :

<VirtualHost 10.10.10.10:8081>
    DocumentRoot /home/site1/www
    ServerName www.example.com
    suPHP_ConfigPath /home/site1/server_config
</VirtualHost>
<VirtualHost 10.10.10.10:8082>
    DocumentRoot /home/site2/www
    ServerName www.example.net
    suPHP_ConfigPath /home/site2/server_config
</VirtualHost>

Each server_config folder contain a php.ini file specific to the vHost. You then just have to change the values of each session.name to unique ones and you're done !
hinom - iMasters 04-Jun-2008 09:00
simple session test

<?php
/* [EDIT by danbrown AT php DOT net:
   The author of this note named this
   file tmp.php in his/her tests. If
   you save it as a different name,
   simply update the links at the
   bottom to reflect the change.] */

session_start();

$sessPath   = ini_get('session.save_path');
$sessCookie = ini_get('session.cookie_path');
$sessName   = ini_get('session.name');
$sessVar    = 'foo';

echo
'<br>sessPath: ' . $sessPath;
echo
'<br>sessCookie: ' . $sessCookie;

echo
'<hr>';

if( !isset(
$_GET['p'] ) ){
   
// instantiate new session var
   
$_SESSION[$sessVar] = 'hello world';
}else{
    if(
$_GET['p'] == 1 ){

       
// printing session value and global cookie PHPSESSID
       
echo $sessVar . ': ';
        if( isset(
$_SESSION[$sessVar] ) ){
            echo
$_SESSION[$sessVar];
        }else{
            echo
'[not exists]';
        }

        echo
'<br>' . $sessName . ': ';

        if( isset(
$_COOKIE[$sessName] ) ){
        echo
$_COOKIE[$sessName];
        }else{
            if( isset(
$_REQUEST[$sessName] ) ){
            echo
$_REQUEST[$sessName];
            }else{
                if( isset(
$_SERVER['HTTP_COOKIE'] ) ){
                echo
$_SERVER['HTTP_COOKIE'];
                }else{
                echo
'problem, check your PHP settings';
                }
            }
        }

    }else{

       
// destroy session by unset() function
       
unset( $_SESSION[$sessVar] );

       
// check if was destroyed
       
if( !isset( $_SESSION[$sessVar] ) ){
            echo
'<br>';
            echo
$sessName . ' was "unseted"';
        }else{
            echo
'<br>';
            echo
$sessName . ' was not "unseted"';
        }

    }
}
?>
<hr>
<a href=tmp.php?p=1>test 1 (printing session value)</a>
<br>
<a href=tmp.php?p=2>test 2 (kill session)</a>
paul at shirron dot net 05-May-2008 07:19
In php.ini, I have:

session.save_path="C:\DOCUME~1\pjs9486\LOCALS~1\Temp\php\session"

I was cleaning out the temp directory, and deleted the php directory. Session stuff quit working. I re-created the php directory. Still no luck. I re-created the session directory in the php directory, and session stuff resumed working.

I would have expected session_start() to have re-created directories in the path, if they didn't exist, but, it doesn't.

Note to self: Don't do that again!!!!
Vextor 04-Apr-2008 08:24
It seems that the garbage engine can't delete the expired session related to the itself. If there is only one session, it won't expire even if it has expired the gc_maxlifetime set.

It will be necessary another client connecting, starting a different session, and the garbage collector of this new session will be able to clean the other expired sessions.

I tested this in Windows with file sessions.
session a emailaddress d cjb d net 28-Mar-2008 11:33
It doesn't appear in the documentation, or in anyone's comment here, but setting session.gc_maxlifetime to 0 means the session will not expire until the browser is closed.

Of course this still doesn't fix the problems associated with the garbage collector doing it's own thing.
The best solution to that still appears to be changing session.save_path
Csar 07-Mar-2008 07:38
There's a bug in Internet explorer in which sessions do not work if the name of the server is not a valid name. For example...if your server is called web_server (_ isn't a valid character), if you call a page which uses sessions like http://web_server/example.php your sessions won't work but sessions will work if you call the script like this
[IP NUMBER]/example.php
Niko 24-Feb-2008 02:07
to anonymousleaf at gmail dot com:

you can get the same result by using this much simplier function call:

<?php
session_start
();
session_regenerate_id();
?>
at the top of the file.
Anonymous 18-Dec-2007 11:10
Hey people,

   This caused a minimal amount of discomfort, but however was quickly solved when I peeked in the php.ini and saw that the entire 'session.save_path' was commented out!  This must have been from the version change from 5.0 to 5.2, and sessions naturally began to work correctly when I removed the comment token and filled in the value like so (using Apache):

session.save_path = "c:\Windows\Temp"

Maybe this will serve as a starting point and save some time for some of you out there who start from a fresh php.ini.

--Matthew
carl /a/ suchideas /o/ com 30-Sep-2007 09:45
Another gotcha to add to this list is that using a relative session.save_path is a VERY BAD idea.

You can just about pull it off, if you're very careful, but note two related points:

1) The path is taken relative to the directory of the ORIGINALLY executed script, so unless all pages are run from the same directory, you'll have to set the directory separately in each individual subfolder

2) If you call certain functions, such as session_regenerate_id(), PHP will try to take the session directory relative to the exectuable, or something like that, creating an error IN the executable. This provides slightly cryptic error messages, like this:

Warning: Unknown: open(relative_path\ilti9oq3j9ks0jvih1fmiq4sv1.session, O_RDWR) failed: No such file or directory (2) in Unknown on line 0

Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (relative_path) in Unknown on line 0

... so don't even bother. Just use

<?php ini_set("session.save_path",dirname(__FILE__)."/relative_path"); ?>

(or equivalent) in a file which you know is always in the same place relative to the file.

{PHP version 5.1.6}
jsnell at e-normous dot com 29-Aug-2007 01:58
Careful not to try to use integer as a key to the $_SESSION array (such as $_SESSION[0] = 1;)  or you will get the error "Notice: Unknown: Skipping numeric key 0. in Unknown on line 0"
Nigel Barlass 28-Jun-2007 06:07
Lima's note on sessions and browser's tabs needs to be modified for my version of php as the call to uniqid('') will return an alphanumeric string.
Hence the ereg statement should be:
if(!ereg('^SESS[0-9a-z]+$',$_REQUEST['SESSION_NAME'])) {...
legolas558 d0t users dot sf dot net 01-May-2007 08:45
To clear out a possible doubt of other readers which have read this part of "Eric dot Deplagne at nerim dot net" note:

--------
In fact, two other variables (at least) play a role in session duration, and will explain that the session might last more than expected. The gc erasing your data is a probabilistic thing. Each time a session is opened, the probability the gc is started is session.gc_probability/session.gc_divisor. session.gc_probability defaults to 1 and session.gc_divisor defaults to 100, which makes a 1% probability.

This is to have sessions long enough. I'm unsure about having sessions lasting exactly the time we want them to.
--------

The gc erasing of the sessions is NOT a probabilistic thing, they are erased ONLY when they are older than the number of seconds specified in "session.gc_maxlifetime" ini setting.

The probabilistic fact is that old sessions will not be erased if the garbage collector is not run frenquently enough, but anyway it is your choice to have a higher or lower "session.gc_probability" on "session.gc_divisor" ratio.

So, talking from the server side point of view, a session can last more than the specified amount of time but not less. And if the client respects the cookies duration (in case of cookie-based sessions) those invalid sessions will not last more than expected.

You finally might want to add a timestamp inside the session and validate its age through it to radically solve the problem, if necessary. Example:

<?php

session_start
();

if (!isset(
$_SESSION['generated']))
   
$_SESSION['generated'] = time();
else {
// if the session is not allowed to live more, regenerate it
   
if (time() - $_SESSION['generated'] > ini_get('session.gc_maxlifetime'))
       
$_SESSION = array('generated' => time());
}
?>
g_s_b 27-Apr-2007 08:37
If you try to use your own session handling functions (eg. for saving session data to DB) make sure session.auto_start directive is 0.

The manual warns about not being able to put objects in your sessions with auto_start=1: I guess that for the same reason your customized handling functions are ignored is sessions start automatically.

Hope this saves somebody a few minutes.
skysama at googles_mail dot com 17-Apr-2007 11:56
If your session are not retrieving correctly make sure that session.cookie_secure is to set to 'Off' if you are NOT going through https. Everytime you navigate the site your session data will not be retrieved and your sessionid will change. It may be obvious but I spent two days trying to figuring this out. Hope it helps someone.
Edemilson Lima <pulstar at gmail dot com> 17-Apr-2007 06:17
Sessions and browser's tabs

May you have noticed when you open your website in two or more tabs in Firefox, Opera, IE 7.0 or use 'Control+N' in IE 6.0 to open a new window, it is using the same cookie or is passing the same session id, so the another tab is just a copy of the previous tab. What you do in one will affect the another and vice-versa. Even if you open Firefox again, it will use the same cookie of the previous session. But that is not what you need mostly of time, specially when you want to copy information from one place to another in your web application. This occurs because the default session name is "PHPSESSID" and all tabs will use it. There is a workaround and it rely only on changing the session's name.

Put these lines in the top of your main script (the script that call the subscripts) or on top of each script you have:

<?php
if(version_compare(phpversion(),'4.3.0')>=0) {
    if(!
ereg('^SESS[0-9]+$',$_REQUEST['SESSION_NAME'])) {
       
$_REQUEST['SESSION_NAME']='SESS'.uniqid('');
    }
   
output_add_rewrite_var('SESSION_NAME',$_REQUEST['SESSION_NAME']);
   
session_name($_REQUEST['SESSION_NAME']);
}
?>

How it works:

First we compare if the PHP version is at least 4.3.0 (the function output_add_rewrite_var() is not available before this release).

After we check if the SESSION_NAME element in $_REQUEST array is a valid string in the format "SESSIONxxxxx", where xxxxx is an unique id, generated by the script. If SESSION_NAME is not valid (ie. not set yet), we set a value to it.

uniqid('') will generate an unique id for a new session name. It don't need to be too strong like uniqid(rand(),TRUE), because all security rely in the session id, not in the session name. We only need here a different id for each session we open. Even getmypid() is enough to be used for this, but I don't know if this may post a treat to the web server. I don't think so.

output_add_rewrite_var() will add automatically a pair of 'SESSION_NAME=SESSxxxxx' to each link and web form in your website. But to work properly, you will need to add it manually to any header('location') and Javascript code you have, like this:

<?php
header
('location: script.php?'.session_name().'='.session_id()
      .
'&SESSION_NAME='.session_name());
?>
<input type="image" src="button.gif" onClick="javascript:open_popup('script.php?<?php
echo session_name(); ?>=<?php echo session_id(); ?>&SESSION_NAME=<?php echo session_name(); ?>')" />

The last function, session_name() will define the name of the actual session that the script will use.

So, every link, form, header() and Javascript code will forward the SESSION_NAME value to the next script and it will know which is the session it must use. If none is given, it will generate a new one (and so, create a new session to a new tab).

May you are asking why not use a cookie to pass the SESSION_NAME along with the session id instead. Well, the problem with cookie is that all tabs will share the same cookie to do it, and the sessions will mix anyway. Cookies will work partially if you set them in different paths and each cookie will be available in their own directories. But this will not make sessions in each tab completly separated from each other. Passing the session name through URL via GET and POST is the best way, I think.
Marcin Wiazowski 03-Apr-2007 01:11
'session.cookie_domain' should be set to empty string for all local domain names, not only for 'localhost' (but should not be empty for local IP addresses):

<?php
ini_set
('session.cookie_domain', (strpos($_SERVER['HTTP_HOST'],'.') !== false) ? $_SERVER['HTTP_HOST'] : '');
?>
Marce! 22-Dec-2006 12:20
Be careful when using use_trans_sid and javascript together. When adding a form dynamically with javascript, you usually need to put it in quotes and use addslashes() for your html code.
This will nicely put slashes into the code for your form and the javascript will work perfectly. Or so you would think. PHP does recognise the form, even with the slashes added. So it will neatly insert a hidden variable to your form, with the name of your session variable and the value of the session ID. This hidden variable isn't slashed though, and it may break your javascript code.

The only solution I came up with, is to manually add the hidden variable, before applying the addslashes() function. It will then be shown correctly, and PHP will not insert the hidden value. Of course you may get both a cookie and the variable, depending on your settings, but it does work.
robin at amiance dot com 26-Nov-2006 10:19
If you want the simplest way there is to log a session out after 30 minutes (or any other period of inactivity) simply add a second line after session_start(), like this:

<?php
session_start
();
setcookie("PHPSESSID",$_COOKIE['PHPSESSID'],time()+1800);
?>

Where 1800 is the time in seconds before the session should expire. PHPSESSID is the default session ID. This way, every time a user loads a page they get their session extended.
nhap24 09-Sep-2006 05:03
I spent about 8 hours debugging a problem with sessions and redirecting, and I finally found the problem, which after looking back, should have been the first thing I tried.

I use sessions to prevent hotlinking, so if someone hotlinks my file, I will redirect them to a different page by re-writing the header information.  When I redirected, I sent path information in the GET data about the file they were trying to access.  Long story short, when I redirected with a forward-slash "/" AFTER the .php, the page would create a different session ID than the rest of my domain was using.  This happened despite the fact that the cookie path was set to "/" (which should have captured any path on my domain). 

The issue was even harder to figure out, because the page with the wrong session ID was NOT creating a second cookie.  The only cookie was the one with the proper ID, but the broken page did not use this cookie (where then, did it get this ID from?).

To fix the problem, I simply removed the forward-slash from the GET data (base64_encoding works nicely).

I imagine this is an issue with my browser parsing the url, but I tried both Opera and Firefox (IE doesn't load anymore :/) and both browsers showed the same problem.

I looked into hidden header data, failure to write the cookie, trans_ses_id (even though it was set to false), HTTP_HOST, everything, but in the end it was just a stupid forward-slash that had done me in.
greenthumb at 4point-webdesign dot de 01-Sep-2006 11:56
Similar to the use of captcha images you can easely track and advise user who don't accept cookies, especially no session cookies without redirecting them.

so here's the deal:

if the main script (which outputs the html) doesn't have a value in it's session which says that a session is running successfully a different value is saved in the session and an image is included in the html which checks wether the session-check value is set or not.

If it's set the image-script sets a confirming value which will verify the session to be running correctly and output a transparent 1*1px gif.

If the value is not set the image outputs an advising image which tells to allow cookies.

You can also wrap the image with a link who refers the user  to a page addressing the cookie issue. If the 1px trans is generated the user will hardly find the link, but if the error-image is generated he will surely be able to click it.

pros:
- works
- no rerouting, you can see the result on the first page opened by the user
- no javascript

cons:
- bad accessebility (if you give the image an alt-text any blind user will read it at least on the first call, but you cold also write this into the alt text... so maybe there are no cons)

i hope this'll help
rehevkor5 at fastmail dot fm 25-May-2006 11:34
If you have a value specified for session.referer_check you may run into difficulty when someone accesses your site and attempts to log in with a mis-capitalized URL.  The logon will fail because any calls to session_start() will result in the existing session being trashed and a new one being created.  This becomes a bigger problem when the logon is followed by a header("Location: ...") redirect, because the session_start() at the top of the page will fail.

Because session_start() always returns true, it's not obvious how to detect when the referer check fails.  To detect it, I have come up with a method which compares the intended session id with the session id after session_start() is run.  If they are different, the user is redirected to the proper location.  This example uses a technique to avoid session id fixation, as well.

<?php
ini_set
('session.referer_check', 'www.yourdomain.edu/ltr/');
ini_set('session.use_only_cookies', 1);
session_name('yourapp'.str_replace('.', '', $_SERVER['REMOTE_ADDR']));
session_start();
if(
$_GET['badreferer'])
    echo
'You tried accessing the site with a bad URL. Try logging on again.';
if(
isUserAuthed($name, $pass))
{
   
$old_sessid = session_id(); //save current session id so we can delete it later
   
if( !session_regenerate_id() ) //get a new session id (must do this before destroying the old session)
       
die("Couldn't regenerate your session id.");
               
   
$new_sessid = session_id(); //save new session id so we can get back to it
               
   
session_id($old_sessid);
    unset(
$old_sessid);
   
session_destroy(); //destroy the session they got before they logged in
               
   
session_id($new_sessid);
   
session_start(); //start the new session
               
   
$_SESSION = array(); //not really necessary any more, but still a good idea
               
   
if(session_id() != $new_sessid)
    {
       
/*If this is true, then the session_start() failed to work properly. If session_start() failed to work properly, the most likely cause is that the referer url is different from that set in fuxebox.ini on session.referer_check. The most common cause of this is URL capitalization problems. Therefore, we relocate them to the proper URL, and set a flag to display an error because we can't use pushError() if the session isn't valid. */
                   
       
$good_url = ini_get('session.referer_check');
       
header('Location: http://'.$good_url.'?badreferer=1');
        exit;
    } else {
        unset(
$new_sessid);
       
//Set session variables here
       
$_SESSION['isloggedin'] = 1;
       
        echo
'You have been logged in.';
    }

}
?>
php AT coryforsyth [removeme] d0t com 08-May-2006 07:14
I just finished a marathon debugging session with sessions, and I wanted to share what I learned with the rest of the PHP community because this has been a problem I've battled on several projects before finally solving it today.

I am using sessions to register a user's ID, and every so often, for no apparent reason, the session would seem to expire and my logged-in user would get kicked out.

This is the code I am using to validate a user:
<?php
session_start
();

$auth = false;

if (isset(
$_SESSION['user_id'])) {
  
$user = new User($_SESSION['user_id']);
  
$auth = true;
else {
  
$login = $_REQUEST['login'];
  
$password = $_REQUEST['password'];
  
$login = clean($login);
  
$password = clean($password);
  
// clean() is my own function to escape quotes and so on
  
$user = checkLogin($login,$password);
   if (!
is_null($user)) {
       
$auth = true;
   }
}

if (!
$auth) {
   die(
"you must log in.");
}

// etc etc ... //
?>

I was scratching my head as to why, on about 10% of the times I sent a user to a new page (a PHP page that didn't have any of the sessions stuff--no session_start() and no mention of any session variables), when they came back the session variables were all empty.

I came upon a clue when I used ini_set to change the session.save_path location.  My idea was that maybe the session files in /tmp were being deleted by other users on the system or something.  So I added this line before session_start():
<?php
ini_set
('session.save_path',"/path/to/unique/dir/");
?>
I knew no one else was saving their sessions there, so I started logging in to my page and at the same time checking for the creation of new sess_* files.  I noticed that sometimes, especially when I had problems, a second session file (that was empty) would appear.

What I realized was that the URL was changing from www.coryforsyth.com to coryforsyth.com.  When the presence of the WWW changed, PHP thought it was a different session and created an empty one that caused my script to log me out.  If I went to the location bar of my browser and added/removed the WWW (to the way it had been before), all was well and I was still logged in.

An incredibly thorny problem. I hope this post helps someone else fix it, or even better prevent it.  I changed my hosting preferences to automatically add a WWW to my domain if it wasn't typed that way.

thanks,
Cory Forsyth
brady at volchok dot com 17-Apr-2006 12:15
Session locking (concurrency) notes:

As mentioned several times throughout this section on Sessions, the default PHP session model locks a session until the page has finished loading. So if you have two or three frames that load, and each one uses sessions, they will load one at a time. This is so that only one PHP execution context has write access to the session at any one time.

Some people work around this by calling session_write_close() as soon as they've finished writing any data to the $_SESSION - they can continue to read data even after they've called it. The disadvantage to session_write_close() is that your code still will lock on that first call to session_start() on any session'ed page, and that you have to sprinkle session_write_close() everywhere you use sessions, as soon as you can. This is still a very good method, but if your Session access follows some particular patterns, you may have another way which requires less modification of your code.

The idea is that if your session code <b>mostly</b> reads from sessions, and rarely writes to them, then you can allow concurrent access. To prevent completely corrupted session data, we will lock the session's backing store (tmp files usually) while we write to them. This means the session is only locked for the brief instant that we are writing to the backing store. However, this means that if you have two pages loading simultaneously, and both modify the session, the <i>Last One Wins</i>. Whichever one loads first will get its data overwritten by the one that loads second. If this is okay with you, you may continue - otherwise, use the session_write_close method, above.

If you have complicated bits of code that depend on some state in the session, and some state in a database or text file, or something else - again, you may not want to use this method. When you have two simultaneous pages running, you might find that one page runs halfway through, modifying your text file, then the second one runs all the way through, further modifying your text file, then the first one finishes - and your data might be mangled, or completely lost.

So if you're prepared to debug potentially very, very nasty race conditions, and your access patterns for your sessions is read-mostly and write-rarely (and not write-dearly), then you can try the following system.

Copy the example from session_set_save_handler() into your include file, above where you start your sessions. Modify the session write() method:

<?php
function write($id, $sess_data)
{
  global
$sess_save_path, $sess_session_name;

 
$sess_file = "$sess_save_path/sess_$id";
  if (
$fp = @fopen($sess_file, "w")) {
  
flock($fp,LOCK_EX);
  
$results=fwrite($fp, $sess_data);
  
flock($fp,LOCK_UN);
   return(
$results);
  } else {
   return(
false);
  }

}
?>

You will probably also want to add a GC (Garbage Collection) method for the sessions, as well.

And of course, take this advice with a grain of salt - We currently have it running on our testing server, and it seems to work OK there, but people have reported terrible problems with the Shared Memory session handler, and this method may be as unsafe as that.

You can also consider implementing your own locks for scary concurrency-sensitive bits of your code.
Cosmo 01-Apr-2006 04:47
Fairly new to PHP, I've been looking to alter session timeouts on a shared host where I don't have direct access to configure php.ini.  There doesn't appear to be any easy way to find out how to do this in this manual (nor from a quick web search).

The code below seems to work OK to set session timeout.     a timeout of 30 secs is used for convenient testing.  gc settings must come before session_start().

The garbage collection is made 100% by setting probability and divisor to the same value - if I have correctly understood what these functions do.
 
(on the first pass of the file, there is no session file - that's established only when the script ends for the first time.  Keep reloading to test).

Comments welcome.

<?php
  ini_set
('session.gc_maxlifetime',30);
 
ini_set('session.gc_probability',1);
 
ini_set('session.gc_divisor',1);
   
session_start();
   
// check to see what's happening
$filepath = ini_get('session.save_path').'/sess_'.session_id();
   
if(
file_exists($filepath))
{
   
$filetime = filemtime ($filepath);
   
$timediff = mktime() - $filetime;
    echo
'session established '.$timediff.' seconds ago<br><br>';
}
?>
crown2gain at yahoo dot com 01-Mar-2006 10:19
I just spent a lot of time trying to figure out why my session variables were not available after I seemed to have set them(could echo after setting).  I use the same script for several different functions, so the user may reload the page for other purposes.  Someone else posted the use of session_write_close();  before a Location redirect.  This also worked in put this after I set the session variables the variables are available when the page reloads for another function.

<?php
$_SESSION
['guid'] = $guid;
$_SESSION['userdata'] = $response;
session_write_close();
?>
a l bell at hutchison dot com dot au 28-Feb-2006 03:17
Please Note;

Internet explorer users beware.

When using session_start() to begin a session this session will remain open until the page has finished loading or it is explicitly terminated.

You can lose the session however if the the page contains a reference to <img src=""> with name and id references (which may be used if the image is referencing a dynamic image, called by javascript)  This seems to casue IE6 to refresh the page session id and hence loose the session.

This took hours for me to diagnose when users were getting unexpectedly logged out of my site due to this "" in the img src.
kintar at infinities-within dot net 28-Feb-2006 09:10
Important note that it just took me the better part of two hours to figure out:  Even if you're using session_write_close(), calling exit after a redirect will eat your session variables.  I had the following:

Source of register.php:
<?PHP

// Some files included here

// Process our posted form data
$result = processPost();

if (
$result)
{
 
redirect('success.php');
}
else
{
 
redirect('failure.php');
}

exit;
?>

processPost() was setting a couple of session variables, including an error message, but neither results page was seeing those variables.  I removed the exit call from the register page, and all works fine.

/bonks self
hans at nieser dot net 14-Feb-2006 07:15
FreeBSD users, instead of modifying the PHP5 port Makefile, you can either install the session extension using the www/php5-session port, or you can install several extensions at once (you can pick them from a menu) using the lang/php5-extensions port. Same goes for PHP4
just_somedood at yahoo dot com 01-Feb-2006 09:31
If you're running FreeBSD, and installed php5 (have not checked 4) from the ports, and are getting errors saying the session functions are undefined, try running phpinfo().  You'll probably see that the '--disable-all' configure command was used.  To fix, edit the /usr/ports/lang/php5/Makefile, and remove the '--disable-all' line.  In that directory, run a 'make deinstall', if you installed already.  Next, run 'make install' while still in that same directory.  It should work fine after that.
jerry dot walsh at gmail dot com 24-Jan-2006 06:56
If you're using sharedance to distributed php sessions across a group of machines beware of the following:

On a freebsd 6.x system I have observed a huge performance hit caused by dns/host file lookups.

To ensure maximum performance using sharedance you should set the 'SESSION_HANDLER_HOST' constant to an IP rather than a hostname.

When i did this my requests per second jumped from 55 to 389 requests per second!
jazfresh at hotmail dot com 19-Dec-2005 06:55
The vanilla implementation of session will blindly spew back the value of the session_id that the user sends it after URL decoding it. This can be used as an attack vector, by including strings like "%0D%0ALocation:%20http://someothersite.com/%0D%0A" in the cookie. Never trust user input, always cleanse it. If you only expect alphanumerics in the session hash, reject any session_id that doesn't contain it.

<?php
if(!preg_match('#^[[:alnum:]]+$#', $_COOKIE['session_id'])) {
  unset(
$_COOKIE['session_id']);
}
session_start();
?>
Bram 19-Nov-2005 08:39
[editors note]
It should be noted that it's highly recommended to store sessions for each virtual host in seperate directories or in a database.
[/editors note]

I just noticed that it's possible to access the same session through multiple apache virtual hosts.
So keep this in mind when using sessions for anything sensitive, and make sure to encrypt the data (using the mcrypt functions for example, when available).
Lachlan Hunt 10-Nov-2005 06:10
> Note:  The arg_separator.output  php.ini directive allows to customize the argument seperator. For full XHTML conformance, specify &amp; there.

Exactly the same rule applies to HTML as well, there is abolutely no reason why this should not be set to &amp; by default.  The only difference is that in XHTML, XML error handling defines that it's a well formedness error.  For HTML, error handling was not so well defined nor sanely implemented and tag soup parsers just accept it, but that doesn't make it right.

arg_separator.output *MUST* be set to either of these if you're outputting either HTML or XML:

arg_separator.output = "&amp;"
arg_separator.output = ";"

http://www.w3.org/QA/2005/04/php-session
christopher dot klein at ecw dot de 23-Oct-2005 11:26
If you have trouble with Internet Explorer 6 and non-working sessions (all session-data is lost after clicking on a link), please look user-hints for setcookie().
You have to add the following line after session_start() to get sessions working:

<?php
 
// Initalize session
 
session_start();
 
// Send modified header
 
header('P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"');
?>
akoma at t3 dot rim dot or dot jp 19-Sep-2005 03:50
If your are using UTF-8, make sure your source
code editor to do not put the BOM mark
(unicode sign) at the top of your source code. so
it is sent before session_start() causing "headers
already sent" message on httpd error log.
fasteddie at byu dot edu not_this_part 16-Aug-2005 08:43
I hope this helps someone:
---PHP SESSIONS NOT WORKING---
My sessions wouldnt ever load from disk. The sessions would start just fine, and a session file would be created and written to disk. (BTW, I'm on a win XP box, Apache 2.0.54, PHP version 5.0.4.) However, next time I loaded the page, the old session would not be used. Instead, a NEW session was created. For me, this happened no matter what computer I was using, whether it was the server (localhost) or a client (remote). A new session was created EVERY TIME I loaded the page.. it was annoying. After a few hours of googling, I gave up and decided to mess around in the php.ini file. I changed this line:
session.cookie_path = /
to this:
session.cookie_path =

Now, php sessions are loaded properly.

I havent tried many things but I think maybe it is because windows needs backslashes (\) instead of forward slashes (/), and if you just leave it blank, it turns out ok.
artistan at cableone dot net 08-Aug-2005 10:29
I rewrote adodb's session management class to work across servers with database managed sessions.  Take a look at http://phplens.com/lens/lensforum/msgs.php?id=13428
Christian Boltz <php-manual at cboltz dot de> 28-Jul-2005 04:33
Another note about session.bug_compat_42 and bug_compat_warn.

[full error message:
    "Your script possibly relies on a session side-effect which existed
    until PHP 4.2.3. Please be advised that the session extension does
    not consider global variables as a source of data, unless
    register_globals is enabled. You can disable this functionality and
    this warning by setting session.bug_compat_42 or
    session.bug_compat_warn to off, respectively."
]

The following short script causes the bug_compat_42 warning to appear.

<?php
  session_start
();
 
$_SESSION['var'] = NULL;
 
$var = "foo";
?>

It took me an hour to find out this :-(  - so I post it here to avoid
that more people need such a long time.

Conclusion and test results:

You'll get this warning if $_SESSION['var'] contains NULL and you assign
anything (except NULL) to the global variable $var.

The warning will _not_ appear:
- if $_SESSION['var'] contains anything else   - or -
- if you don't use a global variable named $var
d43m0n at shaw dot ca 18-Jul-2005 01:19
Hello,

I posted earlyer about a issue/bug with Windows servers handling sessions. If you did not read it, it was based on the fact that if you can use ini_set to re-define the session.save_path to a relitive location. PHP will instead use it as the exact location with out looking at the directory where your script is bein execute, thus to say, the session file is not created, or re-read. This of course only occurs if you use <?php reregister_id() ?>. This function is told to open the requested session file, obtain the varibles, regenerate an id for that session, create the new session file and then send the cookie header to the client, of course I did not create this function, so it may not be in that order.

The following code will generate the error that I speak of, and will not successfully generate the new session id, of course like I said above, this only accours on PHP 5 & 5.0.4 under the Windows Environment.

<?php

  define
("_PATH_TMP", "./tmp");
 
ini_set('session.save_path', _PATH_TMP);
 
session_start();
 
$_SESSION['sid']['obsolete'] = session_id();
 
session_regenerate_id();
 
$_SESSION['sid']['replaced'] = session_id();
 
print_r($_SESSION);

?>

(I know that PHP may use defined constants that include '_' characters at the beggining, if it has not already, but I am taking that chance atm...)

This can simply be resolved by using the following code:

<?php
  define
("_PATH_TMP", dirname($_SERVER['SCRIPT_FILENAME']) . "/tmp");
 
ini_set('session.save_path', _PATH_TMP);
 
session_start();
 
$_SESSION['sid']['obsolete'] = session_id();
 
session_regenerate_id();
 
$_SESSION['sid']['replaced'] = session_id();
 
print_r($_SESSION);
?>

As you can see it uses the uses the servers environment to assurtain the exact location to the script, then locates the next root directory of it, and then allows you to define the tmp directory.

* Of course, you dont need to use a tmp directory, and this issue only occurse when using subdirectorys, I found that the following works just aswell, but this did not fit my needs!

<?php

  define
("_PATH_TMP", "./");
 
ini_set('session.save_path', _PATH_TMP);
 
session_start();
 
$_SESSION['sid']['obsolete'] = session_id();
 
session_regenerate_id();
 
$_SESSION['sid']['replaced'] = session_id();
 
print_r($_SESSION);

?>
nigelf at esp dot co dot uk 16-Jun-2005 04:52
Session data is not available to an object's __destruct method as sessions are closed before the object is 'destroyed'.
Richard [at] postamble [dot] [co] [uk] 13-Jun-2005 07:44
Having to use transparent on a system where trans_sid was not compiled, I came up with the folowing ob_start handler:
<?php
function ob_sid_rewrite($buffer){
   
$replacements = array(
       
'/<\s*(a|link|script)\s[^>]*(href|src)\s*=\s*"([^"]*)"/',
       
'/<\s*(a|link|script)\s[^>]*(href|src)\s*=\s*\'([^\'<>]*)\'/',
        );
         
  
$buffer = preg_replace_callback($replacements, "pa_sid_rewriter", $buffer);

  
$buffer = preg_replace('/<form\s[^>]*>/',
       
'\0<input type="hidden" name="' . session_name() . '" value="' . session_id() . '"/>', $buffer);
       
   return
$buffer;
}

function
pa_sid_rewriter($matches){
   
$buf = $matches[0];
   
$url = $matches[3];
   
$url_orig=$url;
    if (
$url[0]=='/' || $url[0]=='#' || preg_match('/^[A-Za-z0-9]*:/', $url))
        return
$buf;

   
$ses_name = session_name();
    if (
strstr($url, "$session_name="))
        return
$buf;
   
   
$p = strpos($url, "#");
   
$ref = false;
    if(
$p){
       
$ref = substr($url, $p);
       
$url = substr($url, 0, $p);
    }
    if (
strlen($url)==0)
        return
$buf;
    if (!
strstr($url, "?"))
       
$url.="?";
    else
       
$url.="&amp;";
   
$url.=session_name() ."=".session_id();
    if(
$ref)
       
$url.=$ret;
    return
str_replace($url_orig, $url, $buf);
}
?>

It adds a field to urls and a fake form entry.

You can start the rewrite by doing the folowing at the start of the script:
<?php
function pa_set_trans_sid(){
    if (
defined('SID') ){ // use trans sid as its available
       
ini_set("session.use_cookies", "0");
       
ini_set("session.use_trans_sid", "true");
       
ini_set("url_rewriter.tags", "a=href,area=href,script=src,link=href,"
. "frame=src,input=src,form=fakeentry");
    }else{
       
ob_start('ob_sid_rewrite');
    }
}
?>
trev at beammeupnowplease dot com 03-Jan-2005 08:09
You can't turn off session.use_trans_sid on an individual script basis until PHP5.

However, if you use ini_set('url_rewriter.tags', ''); at the top of your script this will stop the SID being written to the URL's in PHP4.

Hopefully will save someone else a frustrating couple of hours.

Trev
Michael Wells 22-Nov-2004 09:04
If you are trying to share sessions across a cluster of servers, and don't want to use NFS, or a relatively heavy and slow RDBMS, there is an excellent tool called ShareDance that can do it over a simple TCP protocol. ShareDance comes complete with a PHP interface example and works 'out of the box' for me.

http://sharedance.pureftpd.org/

My thanks to Frank Denis for writing this elegant, valuable piece of software.
Dopey 02-Sep-2004 11:06
Be careful when using the Content-Length header with session.use_trans_sid enabled. Technically, it might not be a bug, but PHP does not update the header when it adds the session ID to links in a page. The result is that only partial content is shown in a browser.

In short: if you use ob_get_length to figure out Content-Length, turn session.use_trans_sid off!
schulze at telstra dot com dot not dot this dot bit 06-Jun-2004 04:10
sessions not sticking and cookies not setting with IE? took me ages to find the problem.

you need a 'compact privacy policy'! it's not hard once you know how!

this was too much for me: http://www.w3.org/TR/P3P/

but http://www.sitepoint.com/article/p3p-cookies-ie6/2 is very easy to apply

and a visit to this site is very worthwhile: http://www.privacycouncil.com/freep3pfix.php

happy PHP to all!

Erich
Afternoon 04-May-2004 12:28
I found a good solution to create a persistent session by storing a persistence flag, ironically, in the session itelf. I start the session (which sends a Set-Cookie with no expiry time), read the flag and then, if the user wants a persistent session, stop and restart the session with the expiry time set using session_set_cookie_params, which then sends a cookie with a good expiry time. This solution has been quickly tested with all major browsers and seems to work.

I have outlined the whole process in my blog: http://aftnn.org/journal/508
pautzomat at web dot de 19-Nov-2003 12:05
Be aware of the fact that absolute URLs are NOT automatically rewritten to contain the SID.

Of course, it says so in the documentation ('Passing the Session Id') and of course it makes perfectly sense to have that restriction, but here's what happened to me:
I have been using sessions for quite a while without problems. When I used a global configuration file to be included in all my scripts, it contained a line like this:

$sHomeDirectory = 'http://my.server.com/one/of/my/projects'

which was used to make sure that all automatically generated links had the right prefix (just like $cfg['PmaAbsoluteUri'] works in phpMyAdmin). After introducing that variable, no link would pass the SID anymore, causing every script to return to the login page. It took me hours (!!) to recognize that this wasn't a bug in my code or some misconfiguration in php.ini and then still some more time to find out what it was. The above restriction had completely slipped from my mind (if it ever was there...)

Skipping the 'http:' did the job.

OK, it was my own mistake, of course, but it just shows you how easily one can sabotage his own work for hours... Just don't do it ;)
ricmarques at spamcop dot net 15-Oct-2000 05:16
Regarding session.cache_limiter :

For those of you who - like me - had trouble finding the meaning of the possible values (nocache, public and private), here's the explaination taken from the HTTP 1.1 Specification at
http://www.w3.org/Protocols/rfc2068/rfc2068


"14.9.1 What is Cachable

[snip]

public
  Indicates that the response is cachable by any cache, even if it would normally be non-cachable or cachable only within a non-shared cache. (See also Authorization, section 14.8, for additional details.)

private
  Indicates that all or part of the response message is intended for a  single user and MUST NOT be cached by a shared cache. This allows an origin server to state that the specified parts of the response are intended for only one user and are not a valid response for requests by other users. A private (non-shared) cache may cache the response.

  Note: This usage of the word private only controls where the response may be cached, and cannot ensure the privacy of the message content.

no-cache
  Indicates that all or part of the response message MUST NOT be cached anywhere. This allows an origin server to prevent caching even by caches that have been configured to return stale responses to client requests.

  Note: Most HTTP/1.0 caches will not recognize or obey this directive."
shanemayer42 at yahoo dot com 19-Aug-2000 07:11
Session Garbage Collection Observation:

It appears that session file garbage collection occurs AFTER the current session is loaded. 

This means that:
even if session.gc_maxlifetime = 1 second,
if someone starts a session A and no one starts a session for an hour,  that person can reconnect to session A and all of their previous session values will be available (That is, session A will not be cleaned up even though it is older than gc_maxlifetime).

 
show source | credits | sitemap | contact | advertising | mirror sites