I need to manage multiple sessions in a website. I need to start a private sessions which is very page specific so it will terminate once I walk away from the page. But When I browse to previous page, i should be able to use my old session also. For example:
Page A -> Starts Session A
Page A -> is forwarded to Page B
Page B -> Start its own private Session B
Page B -> Completes the tasks and Terminates its private session B
Page B -> Redirects to Page A
Page A -> Again display the page using its old Session A
Can I start multiple sessions within a same website like this? If yes, How can I manage this?
You can use session_name for this, but if page B is killing its session as soon as a single page view is complete, it seems like a waste of time to use a session in the first place.
Perhaps something like;
$_SESSION[$_SERVER['PHP_SELF']]['name'] = $value;
//Page X termination
unset($_SESSION[$_SERVER['PHP_SELF']]);
Just tersely tossing out ideas here.
Expanding on the privatization of session data; A wrapper could help:
class Session implements ArrayAccess{
private $_data = array();
public function __construct(){
$this->_data = $_SESSION;
}
public function offsetSet($offset, $value){
$this->_data[$_SERVER['PHP_SELF']][$offset] = $value;
}
public function offsetExists($offset){
return isset($this->_data[$_SERVER['PHP_SELF']][$offset]);
}
public function offsetUnset($offset){
unset($this->_data[$_SERVER['PHP_SELF']][$offset]);
}
public function offsetGet($offset){
return isset($this->_data[$_SERVER['PHP_SELF']][$offset])
? $this->_data[$_SERVER['PHP_SELF']][$offset]
: null;
}
public function __destruct(){
$_SESSION = $this->_data;
}
}
$session = new Session;
//etc
Given the query string or more is relevant, you could hash the relevant values for the key.
Eg: $key = md5($_SERVER['PHP_SELF'] . $_SERVER['QUERY_STRING']); though using $_SERVER['REQUEST_URI'] as a key may suffice.
Related
I am trying to save my session into memcached, here is some code:
class MemcacheHandler implements \SessionHandlerInterface
{
public function write($session_id, $session_data)
{
$mc = self::getMc();
# test file
file_put_contents('/tmp/session_test', $session_id.'-'.$session_data.'-'.self::$config['expire'].PHP_EOL, FILE_APPEND);
return $mc->set($session_id, $session_data, self::$config['expire']);
}
# Omitting some code
# read() close() destroy() open() gc() getMc() .....
}
Next
session_set_save_handler(new MemcacheHandler(), true);
session_start();
$_SESSION['uid'] = 123456; # write some data
My question is, when i request to the server, There will be a record in /tmp/session_test like 6n0vam0oo8keadg1nl1qab8633-uid|s:6:"123456";-1200。
But when I refresh the page, no record is written! so, if i set up a user login/logout system using session,Would not it be more than a expire time, the user is automatically dropped?
If I changed $_SESSION['uid'] = 78965; Record will be overwritten。Is not php will determine the session_data has changed before write? If there is no change, no write?
My english is poor。。thanks for your time :)
I've been working on the security of my site (PHP) and there's a ton of information to ingest. I've tried to implement security I've researched on OWASP, but one thing I'm a little nervous about, among other things, is how to handle SESSIONS when the user logs out.
Currently all I'm using is:
session_destroy();
But, I've read that I should change the XRSF token and start another SESSION so it forces the user to resubmit login credentials in-turn explicitly ending the users SESSION.
Is session_destroy() enough?
EDIT
I've downloaded michael-the-messenger, which I believe was created by Michael Brooks (Rook) which should be VERY secure, and I saw some code that I might want to use. Is this something that could safely replace the session_destroy() I'm using?
CODE
if($_SESSION['user']->isAuth())
{
/* if they have clicked log out */
/* this will kill the session */
if($_POST['LogMeOut'] == 'true')
{
//When the user logs out the xsrf token changes.
$tmp_xsrf = $_SESSION['user']->getXsrfToken();
$_SESSION['user']->logout();
$loginMessage = str_replace($tmp_xsrf, $_SESSION['user']->getXsrfToken(), $loginMessage);
print layout('Authorization Required', $loginMessage);
}
else
{
header("Location: inbox.php");
//user is allowed access.
}
}
else
{
// code goes on ....
LOGOUT
public function logout()
{
$_SESSION['user'] = new auth();
}
Obviously $_SESSION['user'] = new auth(); reinstantiates the object which sets a private variable $auth to false.
but one thing I'm a little nervous about, among other things, is how
to handle SESSIONS when the user logs out.
According to manual:
In order to kill the session altogether, like to log the user out, the
session id must also be unset. If a cookie is used to propagate the
session id (default behavior), then the session cookie must be
deleted. setcookie() may be used for that.
So, in order to safely destroy a session, we'd also erase it on the client-machine.
session_destroy() along with setcookie(session_name(), null, time() - 86400) will do that.
Apart from that,
What you are doing wrong and why:
Session storage merely uses data serialization internally. By storing
an object in the $_SESSION superglobal you just do
serialize/unserialize that object on demand without even knowing it.
1) By storing an object in $_SESSION you do introduce global state. $_SESSION is a superglobal array, thus can be accessed from anywhere.
2) Even by storing an object that keeps an information about logged user, you do waste system memory. The length of object representation is always greater than a length of the strings.
But why on earth should you even care about wrapping session functionality? Well,
It makes a code easy to read, maintain and test
It adheres Single-Responsibility Principle
It avoids global state (if properly used), you'll access session not as $_SESSION['foo'], but $session->read['foo']
You can easily change its behaivor (say, if you decide to use DB as session storage) without even affecting another parts of your application.
Code reuse-ability. You can use this class for another applications (or parts of it)
If you wrap all session-related functionality into a signle class, then it will turn into attractive:
$session = new SessionStorage();
$session->write( array('foo' => 'bar') );
if ( $session->isValid() === TRUE ) {
echo $session->read('foo'); // bar
} else {
// Session hijack. Handle here
}
// To totally destroy a session:
$session->destroy();
// if some part of your application requires a session, then just inject an instance of `SessionStorage`
// like this:
$user = new Profile($session);
// Take this implementation as example:
final class SessionStorage
{
public function __construct()
{
// Don't start again if session is started:
if ( session_id() != '' ) {
session_start();
}
// Keep initial values
$_SESSION['HTTP_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];
$_SESSION['REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
}
/**
* You can prevent majority of hijacks using this method
*
* #return boolean TRUE if session is valid
*/
public function isValid()
{
return $_SESSION['HTTP_USER_AGENT'] === $_SERVER['HTTP_USER_AGENT'] && $_SESSION['REMOTE_ADDR'] === $_SERVER['REMOTE_ADDR'] ;
}
public function __destruct()
{
session_write_close();
}
/**
* Fixed session_destroy()
*
* #return boolean
*/
public function destroy()
{
// Erase the session name on client side
setcookie(session_name(), null, time() - 86400);
// Erase on the server
return session_destroy();
}
public function write(array $data)
{
foreach($data as $key => $value) {
$_SESSION[$key] = $value;
}
}
public function exists()
{
foreach(func_get_args() as $arg){
if ( ! array_key_exists($arg, $_SESSION) ){
return false;
}
}
return true;
}
public function read($key)
{
if ( $this->exists($key) ){
return $_SESSION[$key];
} else {
throw new RuntimeException('Cannot access non-existing var ' .$key);
}
}
}
Maybe session_unset() is what you are looking for.
I am new to PHP and I want to save an object from this class which I can access in my webservice this object hold a sessions id which can be used for calling an API:
MyObject.php:
class MyObject {
private $sessionId = '';
private function __construct(){
$this->sessionId = '';
}
public static function getInstance() {
if (!$GLOBALS['MyObject']) {
echo 'creating new instance';
$GLOBALS['MyObject'] = new MyObject();
}
return $GLOBALS['MyObject'];
}
public function getSessionsId() {
if ($GLOBALS['MyObject']->sessionId == '') {
// Do curl to get key (works)
if (!curl_errno($curlCall)) {
$jsonObj = json_decode($result);
$sessionID = $jsonObj->session_id;
$GLOBALS['MyObject']->sessionId = $sessionID;
}
}
return $GLOBALS['MyObject']->sessionId;
}
}
Webservice GetKey.php
include 'MyObject.php';
$instance = MyObject::getInstance();
echo $instance->getSessionsId();
The I visit the GetKey.php file it always echoes 'creating new instance'
what you store in $GLOBALS will be destroyed when the page is loaded... that variable is available only when the response is being created...
You don't save an object and use it everywhere (for all users) .. you are in php :) and you can store it anywhere... but if you're in a function then it will be destroyed when you are outside the function...
And in webservices you don't use session because it won't exist at next operation call
In the case that you want to store that variable for multiple requests of the same user you can store it in $_SESSION and not in $GLOBALS...
In PHP everything is destroyed when the user gets the response... (only session is an exception)... a session is like in java or any other language... you have it / user and you can modify it at request time... you don't have something like applicationScope and store there everything for all users... everything is being recreated at every request
I'm working on a small custom CMS and would like to implement flash messages. I have searched for hours, but I can't find anything that behaves the way I want. And I can't seem to make anything work.
I want to be able to pass a variable (via $_SESSION) to another page and, on that next request, it will be removed. I want to be able to use a keep_flash function, in case I don't want the message to be removed with the next server request.
Can anyone send me in the right direction? I can't really make anything work.
Thanks.
EDIT: Here is some code I am playing with. It sort-of works. When you first visit the page, it sets the $_SESSION and everything is fine. But if you refresh, now it deletes the $_SESSION. If you refresh again, it adds it back...etc. So, if you were to visit the page, refresh, then go to another page the flash message wouldn't be in the $_SESSION. So how can I fix this?
class flash
{
private $current = array();
private $keep = array();
public function __construct()
{
if (isset($_SESSION['flash'])) {
foreach($_SESSION['flash'] as $k=>$v)
{
$this->current[$k] = $v;
}
}
}
public function __destruct()
{
foreach ($this->current as $k=>$v)
{
if (array_key_exists($k,$this->keep) && $this->keep[$k] == $v) {
// keep flash
$_SESSION['flash'][$k] = $v;
} else {
// delete flash
unset($_SESSION['flash'][$k]);
unset($this->current[$k]);
unset($this->keep[$k]);
}
}
}
public function setFlash($key,$value)
{
$_SESSION['flash'][$key] = $value;
}
public function keepFlash($key)
{
$this->keep[$key] = $this->getFlash($key);
}
public function getFlash($key)
{
if (array_key_exists($key,$this->current)) return $this->current[$key];
return null;
}
}
basic idea is to have script always check specific variable in session (usually called 'flash') for content - if not empty display and delete it from session. When message is needed just place is same variable in session and next check would pick it up....
keep_flash in your case would not proceed with delete, or move to other place based on your needs.
for implementation just google it - usually it wrapped in some kind of class - I personally like phpclasses.org or part of framework
I'm writing a Ajax/PHP web application. Most ajax calls are using accessing the user object which is stored in the session.
<?php
session_start();
function session_user()
{
static $session_user = null;
if (!isset($session_user))
{
if (isset($_SESSION['user']))
$session_user = unserialize($_SESSION['user']);
else
$session_user = new User();
}
return $session_user;
}
class User {
public $books_borrowed = array();
public function __construct()
{
}
function __destruct()
{
// store the user object in the session upon destruction
session_start();
$_SESSION[ 'user' ] = serialize( $this );
}
function authorise($user_id, $password)
{
// if the user_id and password match, load books_borrowed from the DB
...
}
function deauthorise()
{
session_destroy();
}
}
?>
Ajax calls access the user object like this:
return session_user()->books_borrowed;
Note that the user object stores itself upon destruction, which, as far as I can tell, happens just before the ajax call return.
The reason I'm storing the user object to the session every time the object is destroyed is that it contains other objects (books) that might change during ajax calls, and neither do I want the book object to 'know' about the user object (for reusability) nor do I want to bother with having to remember storing the user object whenever any information within it changes.
Can someone see anything wrong with this strategy?
Thanks
The main strategy when you make a design for brand new application with ajax is not to think of ajax like about something special. It is regular request performed by browser. Absolutely the same like when you open new page by typing url manually and pressing enter.