GAE - PHP sessions not working
I have a web application hosted using Google App Engine and it uses PHP sessions to check if a user is logged in, etc.
session_start()
is present in all scripts via the config.php script that is included in all of them. The app works with iframes and those get the call session_start()
as well.
Locally, it works very well, but when deployed, it acts the same way as the $ _SESSIONS variables expire a short time after the user logs in. For example, sometimes when a user submits a login form, the page is redirected to login again (this is the behavior expected for all pages when the user is not logged in). This is a random event, sometimes it works, sometimes it won't.
I tried to change php.ini with session.cookie_lifetime=0
and put session_start () on the very top line of the script.
Here's the config.php script (which is included in all scripts):
<?php
session_start();
$cur_page = $_SERVER["SCRIPT_NAME"];
if ((!isset($_SESSION['userid']) || $_SESSION['userid']=='') && $cur_page != '/login.php'
&& $cur_page != '/redef-senha.php' && $cur_page != '/nova-senha.php' ) {
// página solicitada, caso seja diferente de scope_home, login, logout
// para garatir sincronia dos Iframes
$request = ( $_SERVER['REQUEST_URI'] != '/login.php'
&& $_SERVER['REQUEST_URI'] != '/scope_home.php'
&& $_SERVER['REQUEST_URI'] != '/logout.php'
&& $_SERVER['REQUEST_URI'] != '/') ? '?r='.$_SERVER['REQUEST_URI'] : '';
header('Location: http://'. ROOT_HOST . '/login.php'.$request ); // não, redireciona
die(); // pára execução do restante do script
}
And here is login.php (as an example):
<?php
// vincular arquivos de configurações e classes
require_once($_SERVER['DOCUMENT_ROOT']. '/config.php');
require_once($_SERVER['DOCUMENT_ROOT']. '/head.php');
use orm\orm\TblUsuarioQuery As UsuarioQuery;
use orm\orm\TblGrupoQuery As GrupoQuery;
$redirect = isset( $_GET['r'] ) ? $_GET['r'] : '/scope_home.php';
// Checar se o login está correto
$errmsg = "Entre com seu usuário ou e-mail e senha:";
if (isset($_POST['user']) && isset($_POST['pass'])) {
$user = filter_var($_POST['user'], FILTER_SANITIZE_STRING);
$pass = filter_var($_POST['pass'], FILTER_SANITIZE_STRING);
$q = new UsuarioQuery();
if ( strpos($user, '@') !== false ) {
$usuario = $q->filterByEmail($user)->findOne();
} else {
$usuario = $q->filterByLogin($user)->findOne();
}
if ( $usuario == null ) {
$errmsg = "Usuário ou e-mail não existe. Verifique e tente novamente:";
} else {
$q = new GrupoQuery();
$grupo = $q->filterByTblUsuario($usuario)->findOne();
if ( !password_verify($pass, $usuario->getSenha())) {
$errmsg = "Usuário ou senha incorretos. Verifique e tente novamente:";
} else {
/* inicia a sessão */
$_SESSION['username'] = $usuario->getLogin();
$_SESSION['userid'] = $usuario->getCodUsuario();
$_SESSION['empresa'] = $grupo->getCodEmpresa();
}
}
}
// Usuário logado?
if (isset($_SESSION['userid'])) {
// redireciona para o url solicitado
header('Location: http://'. ROOT_HOST . $redirect); // sim, redireciona
}
?>
source to share
The default deployment uses multiple instances, and sessions seem to be kept private per instance. If you reload the page several times, you will see that your session sometimes exists and does not exist otherwise when switching between instances.
In a standard environment, GAE seems to be replacing session storage with shared storage; in a flexible environment, it doesn't look like this.
You should be able to configure PHP to use memcache storage for sessions, but in flex you need to provide your own memcache server. The docs point to using redislabs as a vendor that can provide memcache running inside the same datacenters as your GAE application. In php.ini add:
session.save_handler = memcached
session.save_path = "host:port"
where host:port
are the settings that redislabs gives. You can also use a redis instance instead of memcache, but I didn't get this to work with the password. I also didn't get a memcached session to work with a password.
source to share