Change Session ID Once Started - php

I am using Zend framework 1 and I need to change the session id at runtime with a predefined prefix, however I am getting the following error "The session has already been started. The session id must be set first." The issue is that the session state still remains started even after calling the destroy and writeclose. I also tried using the php methods unset & destroy but still same issue.
$oldSession = new Zend_Session_Namespace();
Zend_Session::destroy();
Zend_Session::writeClose();
$sessId = "dskjfghdsjfhsdkf"; //Random hash
Zend_Session::setId("myprefix".$sessId);
$newSession = new Zend_Session_Namespace();
foreach($oldSession as $idx => $data){
$newSession->$idx = $data;
}

Looks like it is not possible,
Snippet from Zend_Session.php:
if (!self::$_unitTestEnabled && defined('SID')) {
/** #see Zend_Session_Exception */
require_once 'Zend/Session/Exception.php';
throw new Zend_Session_Exception('The session has already been started. The session id must be set first.');
}

Related

How to insert same `datetime` variable into different tables?

I'd like to store a datetime variable into different tables by using two functions. I use constraint in CI but still have no luck.
This is the constraint:
$date_now = date("ymdhis");
define('TODAY_DATE',$date_now);
These are the functions:
public function save_activity_m(){
foreach($details as $rows){
$stock_in = $rows['product']."_".TODAY_DATE;
$data['STOCK_IN'] = ($rows['product'] == "") ? NULL : $stock_in;
$this->MProduct->ins_product_m($data);
}
echo "<script type='text/javascript'>alert('New stock arrived');window.top.location.reload();</script>";
}
public function save_notifikasi(){
$lampiran = $this->input->post('lamp');
$data['note_date'] = $lampiran."_".TODAY_DATE;
$data['note'] = $this->input->post('isi');
$this->MProduct->ins_notif($data);
echo "<script type='text/javascript'>alert('You have a notification');</script>";
}
How to make the datetime is the same for $data['STOCK_IN'] and $data['note_date']?
Since the web is stateless, no data in a PHP variable will be held from one page (or load) to another; essentially you're booting the application from scratch each time.
The only way around this is to use some sort of semi-persistent storage such as a cookie or session variable (or persistent storage like the database) - setting a constant, e.g. define('TODAY_DATE',$date_now); will only make that data constant for the current execution of the script(s).
This is a basic example using session storage ($_SESSION):
<?php
// crank up the session
// you may well have one running already,
// in which case ignore this
session_start();
// store the execution time for this script
// as a session variable if it's NOT already set
// i.e. don't overwrite it
if(empty($_SESSION['time_now'])) $_SESSION['time_now'] = date("ymdhis");
public function save_activity_m() {
foreach($details as $rows) {
$stock_in = $rows['product'] . "_" . $_SESSION['time_now'];
$data['STOCK_IN'] = ($rows['product'] == "") ? NULL : $stock_in;
$this->MProduct->ins_product_m($data);
}
echo "<script type='text/javascript'>alert('New stock arrived');window.top.location.reload();</script>";
}
/**
* Assuming this is the last thing you want to
* do with 'time_now' you should unset it here
*/
public function save_notifikasi() {
$lampiran = $this->input->post('lamp');
$data['note_date'] = $lampiran . "_" . $_SESSION['time_now'];
$data['note'] = $this->input->post('isi');
$this->MProduct->ins_notif($data);
// since we're done with the 'time_now' session
// variable we need to unset it...
unset($_SESSION['time_now']);
echo "<script type='text/javascript'>alert('You have a notification');</script>";
}
// just to be on the safe side unset the 'time_now' session var
// if it's older than 1 minute - otherwise future calls to this
// script, by the same user, during the same session will use
// the stored value from $_SESSION['time_now']
if(isset($_SESSION['time_now'])) {
$sessionTime = DateTime::createFromFormat('ymdhis', $_SESSION['time_now']);
$oneMinuteAgoTime = new DateTime('-1 minute');
if($sessionTime < $oneMinuteAgoTime) {
unset($_SESSION['time_now']);
}
}
The caveat is that because you've stored the time in a session variable, unless you update or unset it, it will always be there (for the current session) - so if the user runs the script again it'll just use the stored time from the session.
I've put in a couple of unset() calls to try and work around this.
See PHP: define. It's a constant and it should have the same value if the two functions executed in the same time the script is running.

PHP session security - canary session

I am learning PHP after using Classic ASP since 2001.
I've come to the point of working out how to secure the admin section of a site I'm working on, and have been reading here:
https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions
I've seen that it appears to be bad practice to bind a session to an IP address - e.g.
Check if the $_SERVER['REMOTE_ADDR'] matches $_SESSION['ip']
As taken from the link above:
Some systems like to bind a session to a particular IP address. This is not generally recommended; Tor users, in particular, will have difficulty staying authenticated. You can enforce this restriction here too.
session_start();
// Make sure we have a canary set
if (!isset($_SESSION['canary'])) {
session_regenerate_id(true);
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
if ($_SESSION['canary']['IP'] !== $_SERVER['REMOTE_ADDR'])) {
session_regenerate_id(true);
// Delete everything:
foreach (array_keys($_SESSION) as $key) {
unset($_SESSION[$key]);
}
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
// Regenerate session ID every five minutes:
if ($_SESSION['canary']['birth'] < time() - 300) {
session_regenerate_id(true);
$_SESSION['canary']['birth'] = time();
}
I can't work this one out - is the blog post saying that it is wrong to bind a session to an IP address, and then posting code showing how you can do that?
Or is the "canary" session code they use not actually binding a session to an IP address?
Assuming the code isn't binding a session to an IP address and that it would be good practice to use it, then I'm a bit confused about how I would use this canary session - would I put this bit on my login page, once a user has successfully logged in:
// Make sure we have a canary set
if (!isset($_SESSION['canary'])) {
session_regenerate_id(true);
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
// set my own session variable as well
if (!isset($_SESSION['name'])) {
$_SESSION['name'] = $name; // $name = value from database
header('Location:admin-home.php');
exit;
}
And then put these bits at the top of any pages which are user protected:
session_start();
// ####################################################################################################
// Is User Logged In?
// ####################################################################################################
$name = $_SESSION['name'];
if (!isset($name)) {
header('Location:login.php');
exit;
}
// ####################################################################################################
// Canary Session?
// https://paragonie.com/blog/2015/04/fast-track-safe-and-secure-php-sessions
// ####################################################################################################
if ($_SESSION['canary']['IP'] !== $_SERVER['REMOTE_ADDR']) {
session_regenerate_id(true);
// Delete everything:
foreach (array_keys($_SESSION) as $key) {
unset($_SESSION[$key]);
}
$_SESSION['canary'] = [
'birth' => time(),
'IP' => $_SERVER['REMOTE_ADDR']
];
}
// Regenerate session ID every five minutes:
if ($_SESSION['canary']['birth'] < time() - 300) {
session_regenerate_id(true);
$_SESSION['canary']['birth'] = time();
}
I will also be using HTTPS for the login and admin pages.
The way PHP handles sessions, is to generate a unique session id for each user, and store it in a cookie (default name PHPSESSID). This works well across IP changes, and gives different session on different browsers on the same machine.
To give more security, you can also save user ip and user agent in session, and check that on every request. I'm not sure whether PHP does this by default or not, but it would be rather simple to implement it.
You can also look for session implementation on famous frameworks (Laravel, Symfony, ...) to see how they do it. I leave it to you to further investigate topic, as it should be a bit of googling and reading source code.

Set cookie fails for first time but works on refresh

Though after reading explanations about setting cookie and not working for first time i find it difficult to resolve the below problem as am new to php and cookies.
I have a webpage with for (e.g) cp.php, login.php, header.php, maindata.php , bottom.php. Whenever i login to the webpage cp.php will be processed from there 1.header.php will be called first 2.maindata.php will be called and 3.bottom.php will be called.
So am setting my cookie at maindata.php and the code is like,
<?php
$cid = $_GET["id"];
$XmlPath = $_GET["path"];
$numpath = $_GET["numpath"];
$finepath =$_GET["finepath"];
$Tech =$_GET["tech"];
$read_str="";
function read($Path)
{
$temp="";
if(file_exists($Path))
{
$library = new SimpleXMLElement($Path,null,true);
foreach($library->children("SAS") as $info){
foreach($info->children("SAS") as $attributes){
$nameVal = $attributes->Name."=".$attributes->Value;
$str_temp .=$nameVal."#";
}
}
}else
{
$str_temp ="NA";
}
return $str_temp;
}
$arrpath =explode(",",$XmlPath);
/*Reading and storing arrpath[0] has the path of xml to be parsed*/
$strG=read($arrpath[0]);
$strC=read($arrpath[1]);
$strB =read($arrpath[2]);
setcookie($cid.'strE',$strG);
setcookie($cid.'comstr',$strC);
setcookie($cid.'basstr',$strB);
(....)
in the same file am reading the cookie using the below code,
$read_str =$_COOKIE[$cid.'strE'].$_COOKIE[$cid.'comstr'].$_COOKIE[$cid.'basstr'];
after this process is done bottom.php will be called and for the first time loading is completed.As i said for the first time am not getting any value in $read_str, but if i refresh the page and do all the process again i am getting the value.
As SETCOOKIE will return TRUE incase of successfully setting cookie i tried putting it in an if-loop and it returned false even for the first time.
kindly assist me in finding where the problem exists!
Make use of isset to check if a cookie exists and then try setting one.
Something like this.
if(!isset($_COOKIE['yourcookie'])) {
setcookie('yourcookie', 'Some data !');
$_COOKIE['yourcookie'] = 'Some data !';
}
echo $_COOKIE['yourcookie'];
I arrived here looking for an answer as well. Here's the deal.
When you set a cookie it can only be accessed on the next page load, that is why you can't access it after you set it. If you really need to work with the cookie data right away, you could set the value directly in global cookie such as:
$_COOKIE['my_cookie'] = 'i am a cookie';
Use setcookie()just the same so you can set expiration, domain, etc..

Trying to read someone's code re cookies

I am trying to read some code here (not my own) and make changes. So far what I can get from reading it is that if a variable named $cuid is NOT set, it sends a user to a splash page. If it IS set, it sets the cookie to the $cuid variable (which is actually not happening, the cookie isn't updated when you come with a new CUID in GET)
Here's the code:
if (!$cuid || $reset)
{
$cuid="";
if( $cuid_demo!="samplecu" && $cuid!="75541953" )
setcookie("cuid","",time() - 31536000); //DELETES COOKIE
$query="UPDATE cusucceed SET kkc_visits=kkc_visits+1 WHERE id = '$cuid'";
$result=dbquery($link, $query) or die("error: ".dberror() );
include("splash.php");
}
else
{
setcookie("cuid","",time() - 31536000); //DELETES COOKIE
setcookie("cuid",$cuid,time()+604800); //1 week.
select_db($link) or die("error: ".dberror() );
if($admin_id)
{
$cuid=$cuid;
$id=$cuid;
}
$query="UPDATE cusucceed SET kkc_visits=kkc_visits+1 WHERE id = '$cuid'";
$result=dbquery($link, $query)or die("Database Server Error 2");
include("index_main.php");
Am I reading that correctly? The else part of the if statement should be setting the cuid cookie to $cuid, if $cuid is set, yes?
If $cuid is unassigned (more explicity, has a false result [albeit 0, false, empty]) or it should be $reset,
- Force-empty the cookie (assuming it's not [what appears to be] a test account)
- Display the splash page.
If $cuid is set (and it's not a $reset),
- Re-declare the cuid cookie, and make it last for a week. Then also display the main page.
In both instances,
- Increment the number of times the found $cuid has visited the page.
Although to be honest, it looks like the author wasn't really sure what they were doing based on duplicated code and that they feel the need to empty a cookie before re-declaring it.

set cookie in zend framework

I am new to zend framework. I have write this code to set cookie in my website.
public function setCookie($data){
$email_cookie = new Zend_Http_Cookie('user_email_id', $data['user_email_id'], $_SERVER['HTTP_HOST'], '', FALSE);
$pass_cookie = new Zend_Http_Cookie('user_password', $data['user_password'], $_SERVER['HTTP_HOST'], '', FALSE);
$cookie_jar = new Zend_Http_CookieJar();
$cookie_jar->addCookie($email_cookie);
$cookie_jar->addCookie($pass_cookie);
}
I dont even know by writing this code, my cookie is set or not?
now If I want to retrieve the cookie then how can I do it?
Zend_Http_Cookie is not for setting cookies. It is a class used by Zend_Http_Client for sending and receiving data from sites that require cookies. To set cookies just use the standard PHP setcookie() function:
setcookie('user_email_id', $data['user_email_id'], time() + 3600, '/');
setcookie('user_password', $data['user_password'], time() + 3600, '/');
this will set cookies that expire in 1 hour. You can then access these on subsequent requests using $_COOKIE['user_email_id'] and $_COOKIE['user_password']; or if you are using ZF's MVC classes: $this->getRequest()->getCookie('user_email_id') (from a controller method).
Your cookies are set by sending response. You can modify response in your code.
$cookie = new Zend_Http_Header_SetCookie();
$cookie->setName('foo')
->setValue('bar')
->setDomain('example.com')
->setPath('/')
->setHttponly(true);
$this->getResponse()->setRawHeader($cookie);
By default, the front controller sends response when it has finished dispatching the request; typically you will never need to call it.
http://framework.zend.com/manual/1.12/en/zend.controller.response.html
Check Zend_Http_Cookie
You will get your cookie like following:
echo $email_cookie->getName(); // user_email_id
echo $email_cookie->getValue(); // Your cookie value
echo ($email_cookie->isExpired() ? 'Yes' : 'No'); // Check coookie is expired or not
Use this way you can do it
in your controller do it code as
$cookie = new Zend_Http_Cookie('cookiename',
'cookievalue',
time() + 7200 //expires after 2 hrs
);
echo $cookie->__toString();
echo $cookie->getName(); //cookie name
echo $cookie->getValue(); //cookie value
Try:
$ret_as = COOKIE_STRING_ARRAY;
Zend_Http_CookieJar->getAllCookies($ret_as);
//Get all cookies from the jar. $ret_as specifies the return type
//as described above. If not specified, $ret_type defaults to COOKIE_OBJECT.
Ref: Zend Cookies

Categories