I'm develop a hybrid application and it will using PHP sessions to save user information. In my case, I tried to used php sessions to save the data, but it doesn't save. And then, to testing in web, the result var is show saved.
Here is my example:
<?php
session_start();
if(isset($_POST["Token"])){
$token = $_POST["Token"];
if (isset($_SESSION['device_token']) && $_SESSION['device_token']) {
$token = $_SESSION['device_token'];
} else {
$_SESSION['device_token'] = "notoken";
}
}
?>
Here is my PHP info:
My php Info 1
My php Info 2
Edit:
<?php
ini_set('session.save_path',$_SERVER['DOCUMENT_ROOT'] .'/phpVar');
session_start();
if(isset($_POST["Token"])){
$token = $_POST["Token"];
$_SESSION['device_token'] = $token;
}
if(isset($_GET['ID'])){
$token = $_SESSION['device_token'];
$member_id = $_GET['ID'];
$_SESSION['ID'] = $member_id;
echo $_SESSION['device_token'] ;
echo $_SESSION['ID'] ;
}
?>
because you missed the }
so, instead of:
if(isset($_POST["Token"])){
$token = $_POST["Token"];
should be:
if(isset($_POST["Token"])){
$token = $_POST["Token"];
}
EDIT
Ok, then try to see whether you session directory is writable:
if (!is_writable(session_save_path())) {
echo "No, it's not. Path:".session_save_path();
}
else{
echo "yes, it's writable";
}
EDIT
when path is not set, you might set it manually just before session_start
ini_set('session.save_path',getcwd(). '/tmp');
and afterwards you need to create tmp folder and give it right permission
Related
I was having issues with the session file being locked, so I added session_write_close() once I was done with the session. The script worked properly before that, however, once I leave the sign-in page now, the session is blank.
Session is started at the top of index.php which includes the sign in page:
$result = 'token_valid';
$_SESSION['user'] = $email;
print_r($_SESSION);
session_write_close();
print_r($_SESSION);
The session data is returned properly both times on the sign-in page.
Array ( [user] => abc#gmail.com ) Array ( [user] => abc#gmail.com )
A link returns to the home page, which calls a function to check if logged in...
function user_is_signed_in() {
print_r($_SESSION);
session_write_close();
if($user == '') {
return False;
}
else {
return True;
}
}
The session no longer has any data.
Full index.php
<?php
session_start();
include_once('fnc/database.php');
include_once('fnc/user.php');
if(!user_is_signed_in()) {
include('sign-in.php');
}
else {
$url = parse_url($_SERVER['REQUEST_URI']);
if(!$url['query'])
{
include('home.php');
}
else {
if(isset($_GET['media']))
{
include($_GET['media'].'.php');
}
if(isset($_GET['user']))
{
include($_GET['user'].'.php');
}
}
}
.
.
Workaround (probably filthy)
Issue seems to be caused by the reading/writing of the actual session file. Used the session_id generated by PHP and just created a secondary session file. Do not save in same folder (or if you do, change the filename) - session_start seems to delete and regenerate the session file PHP manages and you'll lose any data written there.
session_start();
$sess = array();
$sess = $_SESSION;
$sess["id"] = session_id();
//print_r($sess);
session_write_close();
Create session_data in session folder
$session_details = "user|".$email;
$session_file = "/Programs/XAMPP/tmp/session_data/sess_".$sess["id"];
//echo $session_details;
$fh = fopen($session_file, 'w+');
fwrite($fh, $session_details);
fclose($fh);
Read session data from this file instead of the session
$session_path = "/Programs/XAMPP/tmp/session_data/sess_".$sess["id"];
$fh = fopen($session_path, 'r');
$session_file = fread($fh, filesize($session_path));
$exploded_session = explode("\n", $session_file);
$session_data = array();
foreach($exploded_session as $line)
{
$tmp = explode("|", $line);
$session_data[$tmp[0]] = $tmp[1];
}
return $session_data["user"];
fclose($fh);
Requirement: use QRBOT-app to scan a barcode on a mobile and give the number scanned to the website.
Problem: I've a session open (1), from here I'm opening the app (see ScanBardcode.php), I scan and the app returns to the callback-URL including the required parameters. However I do expect it is re-using it's session, it creates a new one (2). Can someone help me? It does have both sessions active and both pages keep using it's own session. I can only test it on my cell phone, which I checked is using each time (the initiate-1 and the callback-2 the same browser)
What I tried already:
1. Pass the sessionID in the callback URL (QRBOT doesn't allow parameters)
2. Set Session.auto_start to 1
ScanBarcode.php
<?php
include_once('../../config.inc.php'); //contains DB connection details and other settings
include_once($fullurl . '../../admin/includes/sessie.inc.php'); //generates session
echo "SessionID=". session_id() . "!";
$_SESSION['BarCode'] = "VoorraadTellen";
echo "Wat gaan we doen? " . $_SESSION['BarCode'] . "</br></br>";
//URL to open qrbot.
echo "click"
?>
ScanBarcodeCallBack.php
<?php
$source = $_GET['x-source'];
$content = $_GET['content'];
$format = $_GET['format'];
include_once('../../config.inc.php');
include_once($fullurl . '../../admin/includes/sessie.inc.php');
echo "Wat gaan we doen? " . $_SESSION['BarCode'] . "</br></br>";
echo "SessionID=". session_id() . "!";
echo $source . $content . $format;
// HERE I WRITE TO THE DB.
?>
sessie.inc.php
<?php
$a = session_id();
if(empty($a))
{
session_start();
}
if(isset($_SESSION['sgebruiker']))
{
$now = time();
if($now - $_SESSION['stijd'] > $_SESSION['maxidle'])
{
$_SESSION = array();
session_destroy();
}
else
{
$_SESSION['stijd'] = $now;
}
}
elseif(isset($_COOKIE['login_cookie']))
{
//Check against db and set cookie.
}
?>
Adding screenshot when I add the sessionId in the URL as a parameter:
enter image description here
Update to ScanBarcode.php
`echo "click"
as far as i know you don't need the whole check with session_id(). PHP Documentation for session_start() says:
session_start() creates a session or resumes the current one based on a session identifier passed via a GET or POST request, or passed via a cookie.
this is also my experience. every time i used session_start() i just put it at the top of every file (or included it like you did)
When you pass the session ID in the URL, you need to use the parameter to set the session ID before calling session_start(). Change sessie.inc.php to:
<?php
if (isset($_GET['s'])) {
session_id($_GET['s']);
}
session_start();
if(isset($_SESSION['sgebruiker']))
{
$now = time();
if($now - $_SESSION['stijd'] > $_SESSION['maxidle'])
{
$_SESSION = array();
session_destroy();
}
else
{
$_SESSION['stijd'] = $now;
}
}
elseif(isset($_COOKIE['login_cookie']))
{
//Check against db and set cookie.
}
?>
Working with both #Tsai and #Barmar we found the solution.
We fixed it by:
- Encoding the URL by using urlencode-function
- Take the sessionID from URL and apply that using session_id-function before initiating the start_session (see also).
The cleaned up code below; hopefully someone would be able to use it also.
ScanBarcode.php
<?php
include_once('../../config.inc.php'); //contains DB connection details and other settings
include_once($fullurl . '../../admin/includes/sessie.inc.php'); //generates session
echo "SessionID=". session_id();
//URL to open qrbot.
$CallbackUrl = "http://ilonashairstyling.nl/2016UAT/module/Ilonas_admin/ScanBarcodeCallBack.php?s=" . htmlspecialchars(session_id());
echo "click"
?>
ScanBarcodeCallBack.php
<?php
$source = $_GET['x-source'];
$content = $_GET['content'];
$format = $_GET['format'];
include_once('../../config.inc.php');
ini_set("session.use_cookies",0);
ini_set("session.use_trans_sid",1);
session_id($_GET['s']);
//print_r($_SESSION); //You can test it with this code
//print(session_id()); //You can test it with this code
ini_set("session.use_cookies",1);
ini_set("session.use_trans_sid",0);
include_once($fullurl . '../../admin/includes/sessie.inc.php');
echo "Wat gaan we doen? " . $_SESSION['BarCode'] . "</br></br>";
echo "SessionID=". session_id() . "!";
echo $source . $content . $format;
// HERE I WRITE TO THE DB.
?>
sessie.inc.php is unchanged
I have the following code which works fine under several linux flavors I have tried (Ubuntu, Debian 8, CentOS 7), however when I use it on windows, the regeneration fails without an error. $duration is a value in the class represented as static $duration = 60 * SESSION_TIMEOUT; where SESSION_TIMEOUT is a constant defined in a config.inc.php file (user setting).
session_start();
self::csrf(false);
if(self::verify(false) === true) {
$_SESSION['expires'] = time() + self::$duration;
}
session_regenerate_id(true);
$id = session_id();
session_write_close();
session_id($id);
session_start();
If I echo $id after the line $id = session_id(); there is a value, however if I echo session_id() after the last session_start(), it is empty. (See session_regenerate_id if you think this method is 'Dodgy' )
I do not know why this regeneration code is failing :
session_regenerate_id(true);
$id = session_id();
// one of the lines below this are causing session_id() to be blank
session_write_close();
session_id($id);
session_start();
Please assist me in identifying what is causing the new session to be blank when it should contain the new session id.
session.save_path = 2;755;d:/server/www/127.0.0.1/sessions
Update: I was able to find this in the log, however the interesting part is the session file is created with data.
PHP Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct (2;755;d:/server/www/127.0.0.1/sessions) in Unknown on line 0
As requested, a sample of $id before calling session_write_close() (and subsequent code), is 9vdom0ghuqkvsdcnkjacurc6rf2n4fn1s1gvfva44okd15jdpm30
Update:
After some more testing, I have traced the problem to be a bit more complex than stated above. The problem I initially had which I believed was a session regeneration issue, is more of a problem where session variables are not being stored. I believe this is still related to session regeneration somewhat on windows, however I still am unable to pinpoint a fix, as this code works beautifully on Linux.
Here is the class (minified):
class session {
static $duration = 60 * SESSION_TIMEOUT;
public static function start() {
session_start();
self::csrf(false);
if(self::verify(false) === true) {
$_SESSION['expires'] = time() + self::$duration;
}
session_regenerate_id(true);
$id = session_id();
session_write_close();
session_id($id);
session_start();
}
public static function csrf($new = false) {
if(!isset($_SESSION['csrf']) || $new === true) {
$_SESSION['csrf'] = sha1(openssl_random_pseudo_bytes(mt_rand(16,32)));
}
return $_SESSION['csrf'];
}
}
The code used to call it, is rather complex (when it comes to determining when to generate a new csrf token), but below is my attempt to extract a chunk from my overall project to demonstrate the usage. The login code behind should suffice I believe to view the logic:
if( session::verify() === true ) {
redirect();
} else {
$error = '';
$token = $_SESSION['csrf'];
if ( !empty($_POST) ) {
if ( isset($_POST['csrf']) ) {
// check CSRF token and if match ti token stored in session
$csrf = trim(filter_input(INPUT_POST, 'csrf', FILTER_SANITIZE_SPECIAL_CHARS, array('flags' => FILTER_FLAG_STRIP_LOW | FILTER_FLAG_STRIP_HIGH)));
if($csrf != $_SESSION['csrf']) { session::destroy(); $error = 'CSRF Attack Detected'; }
if( isset($_POST['username']) && isset($_POST['password']) && empty($error) ) {
// login validation code
if($auth) {
// regenerate csrf token
$token = session::csrf(true);
session::create( $username );
// redirect back to application root
redirect();
}
$error = 'Invalid credentials';
} else {
if(empty($error)) { $error = 'Invalid credentials'; }
}
// user was not authenticated, regenerate csrf token to prevent form spam
$token = session::csrf(true);
} else {
// CSRF token did not match stored token in session
$error = 'CSRF Attack Detected';
}
}
}
The additional methods for my session class as used in the login code are as follows :
Update session data with user information.
public static function create($user) {
$_SESSION['nonce'] = sha1(microtime(true));
$_SESSION['ip'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['agent'] = sha1($_SERVER['HTTP_USER_AGENT']);
$_SESSION['expires'] = time() + self::$duration;
$_SESSION['user'] = $user;
session_regenerate_id(true);
$id = session_id();
session_write_close();
session_id($id);
session_start();
}
Verify posted information matches server session
public static function verify($destroy = false) {
$valid = true;
try {
if( !isset($_SESSION['nonce']) ) { $valid = false; }
if( !isset($_SESSION['user']) ) { $valid = false; }
if( isset($_SESSION['ip']) ) { if($_SESSION['ip'] != $_SERVER['REMOTE_ADDR']) { $valid = false; } } else { $valid = false; }
if( isset($_SESSION['agent']) ) { if($_SESSION['agent'] != sha1($_SERVER['HTTP_USER_AGENT']) ) { $valid = false; } } else { $valid = false; }
if( isset($_SESSION['expires']) ) { if($_SESSION['expires'] <= time()) { $valid = false; } } else { $valid = false; }
} catch (Exception $e) {
$valid = false;
}
if($valid === false) {
if(isset($_SESSION['nonce'])) { unset($_SESSION['nonce']); }
if(isset($_SESSION['ip'])) { unset($_SESSION['ip']); }
if(isset($_SESSION['agent'])) { unset($_SESSION['agent']); }
if(isset($_SESSION['expires'])) { unset($_SESSION['expires']); }
if(isset($_SESSION['user'])) { unset($_SESSION['user']); }
if($destroy === true) {
session_unset();
session_destroy();
}
}
return $valid;
}
Update:
Narrowed this down by running a simple test :
// ensure sessions are writeable
if(!is_writable(session_save_path())) {
// try alternate session path
$_session_save_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sessions';
if(!is_writable($_session_save_path)) {
echo "Can't write sessions"; exit;
} else {
session_save_path(
$_session_save_path
);
}
}
Which echo's the result 'Can't write sessions' meaning it failed all methods to try and write data.
What is interesting here, is that no matter what I do (even setting the root of the drive to 'Everyone' with 'Full' permissions, all subfolders and files seem to have a permanent semi-shaded 'Read Only' checkbox. Beyond this, file_put_contents("hello.txt", "hello"); exit(); works in the root folder of my local site, but not from any subfolder below 2 directories deep -- even after assigning (and checking) permissions. (e.g. d:\server\websites\127.0.0.1\htdocs\ works, but not d:\server\websites\127.0.0.1\htdocs\path1\path2\
Update:
Did some more troubleshooting, and the rabbit hole gets deeper. Ran a script to find what user PHP is running under to better assist in checking permissions:
echo 'Current script owner: ' . get_current_user();
which echo's 'Current script owner SYSTEM'
I followed up with this code :
$new = false;
session_start();
if(!isset($_SESSION['csrf']) || $new === true) {
$_SESSION['csrf'] = sha1(openssl_random_pseudo_bytes(mt_rand(16,32)));
}
session_regenerate_id(true);
$id = session_id();
session_write_close();
session_id($id);
session_start();
Which still failed. I did try something which finally worked, but I really don't feel comfortable with it as it involves not setting the security bits as documented in the php.ini file.
I changed :
session.save_path = "2;755;d:/server/www/127.0.0.1/sessions"
To
session.save_path = "d:/server/www/127.0.0.1/sessions"
And this works, however all the session files are now world accessible.
(Server is the same version of apache and php on all platforms configured with identical php.ini files, and server configuration files as close as possible)
// Read Get cerruncy from URL request
if(in_array("crncy",$get_page_all)) {
$crnc_set = explode("/crncy/",$open_page);
$crnc = $crnc_set[1];
$get_crnc = (string) $crnc;
$_SESSION['xxxc'] = $get_crnc;
}
if($_SESSION['xxxc']){
echo $_SESSION['xxxc'];
}
else {echo 'Noooooooooo';}
My problem: In next refresh $_SESSION['xxxc'] value gets changed.
Use session_start(); at top of the page.
My website works fine on localhost, but once I deploy it to my hosting service, the session stops working.
<?php
session_start();
session_save_path('log/session.txt');
ini_set('session.gc_probability', 1);
error_reporting(E_ALL ^ E_NOTICE);
date_default_timezone_set("Asia/Jakarta");
require_once 'jadwal/calendar/tc_calendar.php';
include "../metode/data.php";
include "../metode/jalan.php";
include "../metode/perintah.php";
include "../metode/gambar.php";
//session
$queryadmin = mysql_query("select * from root");
$dataadmin = mysql_fetch_row($queryadmin);
$id = $dataadmin[0];
$key1 = $dataadmin[1];
if (isset($_POST['admin'])) {
$_SESSION['id'] = $_POST['x'];
$_SESSION['key1'] = $_POST['xx'];
}
if (isset($_POST['root'])) {
$_SESSION['user'] = $_POST['xxx'];
$_SESSION['key2'] = $_POST['xxxx'];
}
if (isset($_POST['clear'])) {
$_SESSION['id'] = "";
$_SESSION['key1'] = "";
$_SESSION['user'] = "";
$_SESSION['key2'] = "";
}
if (isset($_POST['exit'])) {
$_SESSION['id'] = "";
$_SESSION['key1'] = "";
}
//access
if ($_SESSION['id'] == $id && $_SESSION['key1'] == $key1) {
$user = $dataadmin[3];
$key2 = $dataadmin[2];
if ($_SESSION['user'] == $user && $_SESSION['key2'] == $key2) {
mysql_query("insert into root history values('','".$_POST['day']."','".$_POST['time']."')");
print "<br><br><br>";
include_once "jembatan.php";
} else {
include "root.php";
}
}
else {
include "admin.php";
}
?>
If you need me to show any other files, just ask.
Could be the way your hosting set up their PHP. Try printing phpinfo() on the host and check their settings.
To run the phpinfo function, just run a script that looks something like this:
<?php
phpinfo();
?>
The output will include a huge list of settings, but you're looking for this section right her:
Note how my settings says Session Support = enabled. That's what indicates that my host (localhost, in my case) supports sessions.
Make sure there is no space or new line before onpenning the <?php tag, because you code here contains 3 spaces before it.
As late as this answer may be coming in, i recently ran into the same problem and after much trial and error. I found out the having the slightest HTML tag above your session could stop session from not registering.
So ensure the first thing you have at the top is
<?php
session_start();
?>