Memcached+PHP session, write() is not working? - php

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 :)

Related

How to use a SOAP API with login and session codeigniter

I have a set of soap APIs which can perform actions like login,logout,keepalive,access other several resources.Inorder to access the other resources,I have to pass a session id which I got from the login api.The session gets time out in 5minutes.
I am confused on how to make this working.
I am using codeigniter for my project,and I have built one library with the set of soap api requests defined in it.
class Soap_api
{
function __construct()
{
define("UID", "myuser");
define("PWD", "34rf3a45575");
define("API_ENDPOINT", "http://uat-api.testingsoapapi.in/services/smp");
define("PRODUCT_CODE", "24");
$resp = $this->keepAliveLib();
if($resp['ResponseCode'] == '0')
{
define("SessionID",$resp['SessionID']);
}
}
function keepAliveLib()
{
$resp = $this->login();
return $resp;
}
function one
{
//This function needs the sessionID receieved from login function
}
function two
{
//This function needs the sessionID receieved from login function
}
So when ever any of the functions from this class is accessed,the constructor calls the keepAliveLib which calls the login function residing in this class and return the session id to the constructor function and set it as global constant sessionID .So the function which I called will be using the that session ID which is made as a constant.
Is this the standard way of calling APIs which relay on sessions?The login function is called when ever a function is called and creates a different session ID.There is a function keepAlive in the library which can be used to maintaining the session,but instead of using keepAlive , Im logging each time a function in this is accessed.
Is there anything wrong in this flow?Can this be done in some other ways?
ok i'm probably not understanding this fully but would this work?
$resp = $this->keepAliveLib();
if($resp['ResponseCode'] == '0') {
$this->sessionid = $resp['SessionID']); }
else { // fail gracefully }
$this->sessionid is now available to any method in the controller.

php session keep alive to check activity

I read around that there is a way to keep checking every 30sec or so if the user is still active on the website and if not, logout (or do something else)
I have a basic inactivity logout but it only works if the user is on the website, but if the user closes the browser/tab, it won't work
if (isset($_SESSION['time'])) {
$elapsed_time = time() - $_SESSION['time'];
if ($elapsed_time >= 900) {
mysql_query("UPDATE `users` SET `status` = '0' WHERE `user_id` = '$session_user_id'");
session_destroy();
header('Location:index.php');
}
}
$_SESSION['time'] = time();
how can i do it so that the status changes to 0 only after X amount of inactive time (but it doesn't necessarily have to log the user out - just change the status)?
hook the session save handler functions, specifically the garbage collection one.
While the below examples show deleting, you could easily modify it to just set an inactivity flag, which can then be read from your inactivity script.
session_set_save_handler docs
PHP <5.4 From: http://www.sitepoint.com/writing-custom-session-handlers/
session_set_save_handler("open", "close", "read", "write", "destroy", "garbage");
function gc($lifetime) {
$db = new PDO("mysql:host=myhost;dbname=mydb", "myuser", "mypassword");
$sql = "DELETE FROM session WHERE session_lastaccesstime < DATE_SUB(NOW(), INTERVAL " . $lifetime . " SECOND)";
$db->query($sql);
}
//below ones are covered in the article.
function open(){}
function close(){}
function read(){}
function write(){}
function destroy(){}
Php 5.4+ From: http://www.php.net/manual/en/class.sessionhandlerinterface.php#example-4769
Note: this example is file based you would just have to modify it to use database
<?php
class MySessionHandler implements SessionHandlerInterface
{
public function gc($maxlifetime)
{
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}
return true;
}
//below functions are covered in the manual
public function open($savePath, $sessionName){}
public function close(){}
public function read($id){}
public function write($id, $data){}
public function destroy($id){}
}
$handler = new MySessionHandler();
session_set_save_handler($handler, true);
session_start();
Both rely on a good number of users visiting your site. Otherwise if for instance you dont get users for days the like garbage collection function will not be run for days. In cases like that you would have to setup some other system like a cron job to trigger a script every so often.
Delete the files with the following cron:
find .session/ -amin +20 -exec rm {} \;
This will delete session files that have not been accessed for 20 minutes. This will delete all PHP sessions, assuming you are the only person on the server.
More ways to do this are specified in this question: cleanup php session files

How to properly end a users session?

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.

How to save an object in PHP and access it everywhere?

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

The Right Strategy for PHP Session User in Ajax Application

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.

Categories