I've looked at existing answers for my problem.
I've echo'd the value right through the process and right up until the "header('Location" instruction the values remain intact.
I don't think it's a serialization problem as suggested for similar problems...
Here are the relevant bits of the class:
class clsSetUser {
protected $UserID = 0;
public function initUser($id) {
// get user details from database
$this->setUserID($id);
// etc...
}
private function setUserID($value) { $this->UserID = $value; }
public function getUserID() { return $this->UserID; }
}
common.php:
if(unset($clsUser)) $clsUser = new clsSetUser;
login-exec.php:
$clsUser->initUser($id);
header("Location: somewhere.php");
somewhere.php:
echo $clsUser->getUserID();
// here it equals 0
any ideas? does "header" serialize everything?
This is because PHP is actually starting from a clean slate in somewhere.php.
header("Location: somewhere.php"); sends a command the browser to connect to a different page. In this page non of variables of the previous page are available in PHP.
You need to set the userId in the $_SESSION so that you can reload the user from the database when he visits somewhere.php.
login-exec.php
$clsUser->initUser($id);
$_SESSION['user_id'] = $id;
header("Location: somewhere.php");
somewhere.php
$clsUser->initUser($_SESSION['user_id']);
Related
I'm using the spotify api and for some reason their session class blocks to store own data in $_SESSION. As a workaround I wrote a class 'SystemHelper':
namespace App;
class SystemHelper
{
/**
* if session_id is empty string, then session_id has not been initialized
* then set session_id named 'session1'
* start session needs 2 parameters, name and value
* always close session after writing
*
* #param string $name any given name
* #param [type] $value any given value
*
*/
public static function customSessionStore($name, $value)
{
if (session_id() == '') {
session_id('session1');
}
session_start();
$_SESSION[$name] = $value;
session_write_close();
}
It is possible now to store data in $_SESSION but the problem is that as long as I'm logged in with my account (own login form, not spotfiy account), everybody else is logged in, no matter which browser, ip, etc...
I don't know how this can be solved. Shouldn't session_id generate a random id? Anybody can help please?
Leaving out
if (session_id() == '') {
session_id('session1');
}
doesn't solve it because I need to read and delete the data stored in session as well. So, additionally I have in this workaround:
public static function customSessionRead($name)
{
if (session_id() == '') {
session_id('session1');
}
session_start();
session_write_close();
return $_SESSION[$name];
}
and...
public static function customSessionDestroy()
{
session_start();
session_destroy();
}
If i get this right.. all your users get the same session_id().
So they technically share one session. As much as i know, if you start a session, the session_id() will be automattically generated. So you dont need to set the session_id() by yourself.
So your code should look like this:
class SystemHelper
{
/**
* if session_id is empty string, then session_id has not been initialized
* then set session_id named 'session1'
* start session needs 2 parameters, name and value
* always close session after writing
*
* #param string $name any given name
* #param [type] $value any given value
*
*/
public static function customSessionStore($name, $value)
{
session_start();
$_SESSION[$name] = $value;
session_write_close();
}
}
Solved, actually pretty simple. The problem first:
If written like this:
session_id('session1');
in both, customStore and customRead simply means resuming the session. Of course you will always get the same data, no matter which browser, ip, ... that's the point of resuming the session.
What is solved:
session_create_id($name);
So, the full again:
public static function customSessionStore($name, $value)
{
// if (session_id() == '') {
// session_id('session1');
// }
session_create_id($name);
session_start();
$_SESSION[$name] = $value;
session_write_close();
}
and,
public static function customSessionRead($name)
{
// if (session_id() == '') {
// session_id('session1');
// }
session_start();
session_write_close();
return $_SESSION[$name];
}
The session I set is lost after the form is submitted.
I had built the session class to set new session, unset and so on. In function.php of wordpress template.
function.php
if (!session_id()) {
session_start();
}
include get_template_directory() . "/custom/session.php";
Session.php
class session {
function __construct() {
}
function set_flashdata($name, $value) {
$_SESSION[$name] = $value;
}
function flashdata($name) {
if (isset($_SESSION[$name])) {
$str = $_SESSION[$name];
return $str;
} else {
return FALSE;
}
}
function userdata($name) {
if (isset($_SESSION[$name])) {
return $_SESSION[$name];
} else {
return FALSE;
}
}
function set_userdata($name, $value) {
$_SESSION[$name] = $value;
}
function unset_userdata($name) {
if (isset($_SESSION[$name])) {
unset($_SESSION[$name]);
}
}
}
I try to set session as :
<?php
$sess = new session();
$sess->set_userdata('sess_name',"some value");
?>
<form action="get_permalink(212);">
//input buttons
</form>
After submit the form it goes to the permalink(212). Then I tried.
<?php
$sess = new session();
$value = $sess->userdata('sess_name');
var_dump($value); //returns false. That means session is lost after form submit. Why?
?>
You need to move session start/resume into your Session's constructor.
Like so:
class session
{
function __construct()
{
if (! session_id()) {
session_start();
}
}
Another thing to mention, every time you'll do new Session you'll be getting an object of the same functionality working with same global variable $_SESSION.
You don't need more than one $session object, it would be a good time to look into Singleton pattern.
You have to call always session_start() for each request.
The mission of session_start() is:
Creates a new session
Restart an existing session
That means, if you have created a session, and you don't call to the method session_start(), the variable $_SESSION is not going to be fulfilled.
Except: If in your php.ini you have set the option session.auto_start to 1, then, in that case it is not needed to call the session_start() because the variable $_SESSION is fulfilled implicitly.
You need to use wordpress global variable for condition that session is set or not something like :
global $session;
if (!session_id()) {
session_start();
}
include get_template_directory() . "/custom/session.php";
It might be due to www. at the start of your website domain. Make sure that both of pages use the same structure.
Also I faced with the same issue long time ago when the form sends the data to a secured address (https://)
I hope these two items may help you.
Sounds to me like session_start() is not set at the start of the page that get_permalink(212;) refers to.
I have almost no experience with WP itself though, so I might misunderstand the functionality of get_permalink()
I agree with the answer from #rock3t to initialize session in constructor of class, but every time a class object is initiated, it will go to check for session!
Instead, if you are fine, the simplest way to get access to session is by adding following lines to your wp-config.php file before the call to wp-settings
if (!session_id())
session_start();
This will set/initialize session globally and you won't need to set/check for session_start in constructor of a class.
Thank you.
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'm trying to implement and authentication system with jQuery and PHP. All the php work is made in the controller and datahandler class. There is no php code inside the .html files, all the values in .html files are rendered via jQuery that request the data from php server. So what I'm trying to do is:
When user clicks the login button, the jQuery makes a call to the authenticate() method in my controller class, it checks if the user is correct and stuff, and if it is, start the session and set the user_id on the session so I can access it later, and returns the userId to the jQuery client again.
After that, if everything is fine, in jQuery I redirect it to the html file. On the html file I call a jQuery from the <script> tag that will handle other permissions. But this jQuery will access the method getPermissionString (from the same class of authenticate() method mentioned before), and it will need to get the session value set in authenticate method.
The Problem:
When I try to get the session value inside getPermissionString() it says:
Notice: Undefined variable: _SESSION
I've tried to check if the session is registered in the second method, but looks like it's not. Here is my PHP code.
Any idea? Thanks.
public function authenticate($login, $password)
{
$result = $this->userDataHandler->authenticateUser($login, $password);
if(is_numeric($result) && $result != 0)
{
session_start();
$_SESSION["uid"] = $result;
if(isset($_SESSION["uid"]))
{
echo "registered";
$userId = $_SESSION["uid"];
}
else
{
echo "not registered";
}
echo $result;
}
else
{
echo 0;
}
}
public function getPermissionString()
{
if(isset($_SESSION["uid"]))
{
echo "registered";
$userId = $_SESSION["uid"];
}
else
{
echo "not registered";
}
}
Before you can access $_SESSION in the second function you need to ensure that the program has called session_start() beforehand. The global variable is only populated when the session has been activated. If you never remember to start a session before using it then you can change the php.ini variable below:
[session]
session.auto_start = 1
Further, you said that you're using a class for your code. In this case you can also autos tart your session each time the class in created by using magic methods:
class auth {
function __construct() {
session_start();
}
function yourfunction() {
...
}
function yoursecondfunction(){
...
}
}
If you don't have session.auto_start enabled, and authenticate and getPermissionString are called on two different requests, you need to call session_start() in each function.
If you need more information on how the session ID is passed, just read Passing the Session ID
You should not use that function if session is not started. So throw an exception:
public function getPermissionString()
{
if (session_status() !== PHP_SESSION_ACTIVE)
{
throw new Exception('No active session found.');
}
if(isset($_SESSION["uid"]))
{
echo "registered";
$userId = $_SESSION["uid"];
}
else
{
echo "not registered";
}
}
This ensures the pre-conditions of your functions are checked inside the function so you don't need to check it each time before calling the function.
You will now see an exception if you wrongly use that function and it will give you a backtrace so you can more easily analyze your code.
For php sessions to work you have to call session_start() every time you script is requested by the browser.
After validating user input and storing login credentials I start a session by calling session::start and then reload the index.php file by calling general::reload. The I use session::is_start() to determine which page to load from the index file.
I don't think this is working correctly as I always get the same page loaded - b1e.htm.
My concern is that my static class session does not maintain its value between the AJAX/PHP call and the reload index.php call.
Similar posting - here
index.php
include 'b2.php';
if(session::is_start())
{
include 'b2e.htm'; // user is logged in
}
else
{
include 'b1e.htm'; // user is not logged it
}
Snippet - session:start() and session::is_start();
class session
{
protected static $ses_id ="";
public static function start()
{
self::$ses_id = session_start();
}
public static function is_start()
{
return self::$ses_id;
}
public static function finish()
{
self::$ses_id = 0;
$_SESSION=array();
if (session_id() != "" || isset($_COOKIE[session_name()]))
{
setcookie(session_name(), '', time()-2592000, '/');
}
session_destroy();
}
}
Snippet - general::reload()
class general
{
public static function reload()
{
$uri = 'http://';
$uri .= $_SERVER['HTTP_HOST'];
header('Location: '.$uri.'/host_name');
}
You can encapsulate and consolidate session functionality, but you can not fully monitor sessions with a class as php user code is stateless (even when using static keyword)...i.e. it will depend upon SESSION to retain state.
You need to call your session_start(); to actually start the session on each page.