I'm running an application where in the controller I'm trying to set session variables using Zend_Session and Zend_Session_Namespace:
Bootstrap.php
protected function _initSession()
{
Zend_Session::start();
}
SomeController.php
protected function updateQuestionViewsTotal($question)
{
$userSession = new Zend_Session_Namespace('QA_Session');
if (! is_array($userSession->questionViews)) {
$userSession->questionViews = array();
}
// create session array to contain the questions this
// user has viewed.
if(array_search($question->id, $userSession->questionViews) === false) {
$question->views_total++;
$question->save();
}
// ensure that this page is in the array
array_push($userSession->questionViews, $question->id);
$userSession->questionViews = array_unique($userSession->questionViews);
}
As you can see from above, I have within one of my controllers a method with an attempt to use session variables via Zend_Session_Namespace.
However, when I insert a var_dump on the second page load (refresh):
protected function updateQuestionViewsTotal($question)
{
$userSession = new Zend_Session_Namespace('QA_Session');
var_dump($userSession));
if (! is_array($userSession->questionViews)) {
$userSession->questionViews = array();
}
..Please note: this is AFTER I've run it once, so I'm expecting that the session variable has been set. Anyway on every occasion, it is NULL. So it would seem that the variable isn't being written to $_SESSION? What am I doing wrong?
Related
I'm not very sure if this is Joomla or PHP issue in my code. Basically I've two functions, A and B that invoked on page load and onclick event respectively.
On page load, I set session value to loadA. Once click event triggered, I set session value to clickB.
Meanwhile the while loop inside function is running until the condition is met. Inside the loop, it's checking for session value. So if the value updated inside function B, it should also be updated in function A when the while loop check right?
But it's not giving the updated value. Function A still gives loadA as session value inside while loop even after click event took place. How to fix this please?
class XXY(){
public function A()
{
$session = JFactory::getSession();
//set session value on page laod
$this->setSession('loadA');
while (x == y)
{
usleep(10000);
clearstatcache();
$comet = $session->get('runningComet');//giving the first set value, loadA
if($comet !== 'loadA'){
break;
}
}
}
public function B()
{
$session = JFactory::getSession();
$this->setSession('loadB');
$comet = $session->get( 'runningComet');//giving the updated value, loadB
}
public function setSession($currentComet){
$session = JFactory::getSession();
$session->set('runningComet', $currentComet);
}
}
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
class Index extends CI_Controller {
private $data = array();
private $content_data = array();
public function __construct() {
parent::__construct();
if (isset($_GET['m2w'])) {
$stw = switch_to_web();
}
if (isset($_GET['w2m'])) {
$stm = switch_to_mobile();
}
// load mobile or desktop view
}
// Called within an helper function
function switch_to_web() {
return set_cookie('load-web', 'true', '86500');
}
function switch_to_mobile() {
return delete_cookie('load-web');
}
function is_mobile() {
// return true;
$CI = & get_instance();
if ($CI->input->cookie('load-web'))
return false;
$CI->load->library('user_agent');
if ($CI->agent->is_mobile()) {
return true;
}else
return false;
}
I have the above block of code to determine if to load the mobile or web view.
Expected order of execution:
if m2w is set, set the load-web cookie (this is done before the is_mobile function is called
is_mobile function sees the load-web cookie has been set and loads the desktop version
Actual order of execution:
if m2w is set, load-web cookie is called to be set, however the is_mobile function doesn't see it as set hence the desktop version is not loaded
the cookie is set after the is_mobile function has returned true, i check my browser cookies and observed that the cookie was actually set but not at when expected
What am I not getting right?
CI's cookies uses the native setcookie() method of PHP. Cookies requires to be sent in the HTTP headers before being available in the native $_COOKIE variable.
From the PHP doc :
Once the cookies have been set, they can be accessed on the next page load with the $_COOKIE or $HTTP_COOKIE_VARS arrays.
Here's the cookie() method from CI :
function cookie($index = '', $xss_clean = FALSE)
{
// Simply fetch from the $_COOKIE array and do XSS_Clean if needed.
return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
}
In short, you set your cookie correctly, but it won't be available until your next request. It's all because the new value isn't in $_COOKIE array.
You have multiple alternatives to fix that.
You could extend the CI_Input class and modify the set_cookie method to also add your new value to the $_COOKIE array.
You could edit your is_mobile function to also check for the $_GET['m2w'] value. (Not just the cookie.)
Personalty, I think the 2nd solution is the cleanest and easiest to do, but I don't know the full scope of your project.
Hope this helps!
I have a class that loads certain parts of my page. What I want to do is this
index.php
$obj->load('admin');
In my class in the constructor I have a check to see if the URI contains the segment /admin/ and if it does then it auto loads the admin page:
$this->load('admin');
now both work fine, I just realized that if I have both entries in my project then it will load the admin initialization twice.
Is there a way for my to check if the load() method has already been called and if the parameter is == to admin?
One way is to use static cache:
function load($what) {
static $loaded = array();
if (!isset($loaded[$what])) {
// Load..
// Mark as loaded
$loaded[$what] = true;
}
}
class Foo {
private $loaded = false;
function someFunc() {
$this->loaded = true;
}
function loaded() {
return $this->loaded;
}
}
May be Keep a object member variable variable and keep a flag when the load admin is called for first time. Check the flag for during the second call.
Easiest - create additional variable called say '$invokedAlready'. Set it first to 'false'. In your method place this:
if ( $invokedAlready )
{
// do sth
}
else
{
// first invocaion
// do sth else
$invokedFirst = true;
}