I am working on a school project where I need my .php pages communicating. I have header.php where I set connection to the database and start the session. In order to start the session only once, I've used this:
if(session_id() == '') {
session_start();
}
PHP version is PHP 5.3.10-1 ubuntu3.18 with Suhosin-Patch (cli)
I am trying to pass some $_SESSION variables between pages, but they keep being unset when I try to use them on a page that doesn't set them.
I see many people have complained about this, but I still can't find the solution.
login-form.php
<?php
if (isset($_SESSION["login-error"])) {
echo '<p>'.$_SESSION["login-error"].'</p>';
}
?>
login.php
$_SESSION["login-error"]= "Username or password incorrect";
There is a code snippet of what is not working for me.
Thanks
You can try this.
In your function file put this
function is_session_started()
{
if ( php_sapi_name() !== 'cli' ) {
if ( version_compare(phpversion(), '5.4.0', '>=') ) {
return session_status() === PHP_SESSION_ACTIVE ? TRUE : FALSE;
} else {
return session_id() === '' ? FALSE : TRUE;
}
}
return FALSE;
}
Then you can run this in every page you want session started
if ( is_session_started() === FALSE ) session_start();
With this I think you should be good to go on starting your session across pages. Next is to ensure you set a session to a value. If you are not sure what is unsetting your sessions you can try var_dump($_SESSION) at different parts of your code so you be sure at what point it resets then know how to deal with it.
The variables are probable not set, because you haven't activate the session variables with session_start().
session_id() == '' is not a correct conditional . Use instead:
if (!isset($_SESSION)) { session_start();}
if you have session started then you can set a session variable
if (!isset($_SESSION["login-error"])) { $_SESSION["login-error"]= "Username or password incorrect";}
Before you call $_SESSION["login-error"], type session_start(), just for testing, to find when the session signal is missing. You said
PHP $_SESSION variables are not being passed between pages
session_start() and SESSION variables needs to be included at the beginning of EVERY page or at the place where SESSION variables are being called (through a common file, bootstrap, config or sth) at the beginning of EVERY page. ie the command to read those data from the server is needed.
Since my header.php file included "connection.php" file, I put
session_start();
at the beginning of connection.php and deleted it from header.php file. Now it works fine. Thanks all for your help!
PHP sessions rely on components of HTTP, like Cookies and GET variables, which are clearly not available when you're calling a script via the CLI. You could try faking entries in the PHP superglobals, but that is wholly inadvisable. Instead, implement a basic cache yourself.
<?php
class MyCache implements ArrayAccess {
protected $cacheDir, $cacheKey, $cacheFile, $cache;
public function __construct($cacheDir, $cacheKey) {
if( ! is_dir($cacheDir) ) { throw new Exception('Cache directory does not exist: '.$cacheDir); }
$this->cacheDir = $cacheDir;
$this->cacheKey = $cacheKey;
$this->cacheFile = $this->cacheDir . md5($this->cacheKey) . '.cache';
// get the cache if there already is one
if( file_exists($this->cacheFile) ) {
$this->cache = unserialize(file_get_contents($this->cacheFile));
} else {
$this->cache = [];
}
}
// save the cache when the object is destructed
public function __destruct() {
file_put_contents($this->cacheFile, serialize($this->cache));
}
// ArrayAccess functions
public function offsetExists($offset) { return isset($this->cache[$offset]); }
public function offsetGet($offset) { return $this->cache[$offset]; }
public function offsetSet($offset, $value) { $this->cache[$offset] = $value; }
public function offsetUnset($offset) { unset($this->cache[$offset]); }
}
$username = exec('whoami');
$c = new MyCache('./cache/', $username);
if( isset($c['foo']) ) {
printf("Foo is: %s\n", $c['foo']);
} else {
$c['foo'] = md5(rand());
printf("Set Foo to %s", $c['foo']);
}
Example runs:
# php cache.php
Set Foo to e4be2bd956fd81f3c78b621c2f4bed47
# php cache.php
Foo is: e4be2bd956fd81f3c78b621c2f4bed47
This is pretty much all PHP's sessions do, except a random cache key is generated [aka PHPSESSID] and is set as a cookie, and the cache directory is session.save_path from php.ini.
Related
I have two methods which work without problems
public static function appendGamer($gamer) {
file_put_contents(self::$fileName, $gamer, FILE_APPEND);
}
and
private function selectLastGamer() {
$gamers = file(self::$fileName);
if (sizeof($gamers) > self::$totalGamers) {
self::$totalGamers = sizeof($gamers);
return trim($gamers[self::$totalGamers - 1]);
}
return "";
}
Now I want everything to be stored in session vars rather than traditional text files. So i rewrite these functions the following way
public static function appendGamer($gamer) {
$old = trim($_SESSION["gamers"]);
$_SESSION["gamers"] = ($old == "") ? $gamer : $old . PHP_EOL . $gamer;
}
and
private function selectLastGamer() {
$gamers = explode(PHP_EOL, $_SESSION["gamers"]);
if (sizeof($gamers) > self::$totalGamers) {
self::$totalGamers = sizeof($gamers);
return trim($gamers[self::$totalGamers - 1]);
}
return "";
}
But now these functions don't work. I mean now selectLastGamer always returns empty string. The session variable is automatically created in constructor so it is always set. What's wrong with new version of these functions?
You should start session on every page like
if( session_status() != PHP_SESSION_DISABLED )
{
session_start();
}
OR
if( session_status() == PHP_SESSION_NONE || session_status() == PHP_SESSION_ACTIVE)
{
session_start();
}
Because session_status() returns any one of the following value at a time.
PHP_SESSION_DISABLED if sessions are disabled.
PHP_SESSION_NONE if sessions are enabled, but none exists.
PHP_SESSION_ACTIVE if sessions are enabled, and one exists.
Hope it ll work for you.
Start session on every page you want to access the session variable set/get using session_start(); at the top of the page.
On main page and also on the page where functions are defined.
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 was wondering, what's the best way to store messages for the user in PHP. With messages i mean something like
Authentication successful
or
Please enter a valid e-mail address
Currently I'm working on a project where they are stored in the $_SESSION variable, but I don't think this is a good solution.
Short explanation how I do it at the moment (The class Message was created by me)
$_SESSION["msg"][] = new Message("...");
and
foreach ( $_SESSION ["msg"] as $msg ) :
echo $msg->getText();
endforeach;
unset ( $_SESSION ["msg"] );
This is just a simplified version of the complete code, but you should get the idea.
EDIT: Forgot to say, that I'm working with an MVC framework and want to speperate the logic from the output.
One can only speculate on the nature/contents of your Message Class. However, here; attempt was made to simulate a mock-up of a class called Message; also the Usage in your View Script was shown below the Class. Be sure that $_SESSION is active on both Scripts.... Perhaps, this may shed some new light on how to go about your unique case:
<?php
//FIRST CHECK IF SESSION EXIST BEFORE STARTING IT:
if (session_status() == PHP_SESSION_NONE || session_id() == '') {
session_start();
}
class Message {
protected $msg;
public function __construct() {
if(!isset($_SESSION['msg'])){
$_SESSION['msg'] = array();
}
}
public function setText($message){
if(!in_array($message, $_SESSION['msg'])){
$_SESSION['msg'][] = $message;
}
}
public function getText(){
return "Some Logic for getting Message";
}
}
?>
<?php
// INSIDE OF YOUR VIEW SCRIPT; AT THE VERY TOP, ENABLE SESSION AS WELL:
//FIRST CHECK IF SESSION EXIST BEFORE STARTING IT:
if (session_status() == PHP_SESSION_NONE || session_id() == '') {
session_start();
}
// THEN LOOP THROUGH THE SESSION DATA FOR MESSAGES TO BE DISPLAYED
$msg = new Message();
if(isset($_SESSION['msg'])) {
foreach ($_SESSION ["msg"] as $msg) :
echo $msg->getText();
endforeach;
unset ($_SESSION ["msg"]);
}
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.