My Code:
class cdbsHandler
{
[...]
private $link;
function __construct($mysqld)
{
[...]
$this->link = mysql_connect(
$mysqld['host'], $mysqld['user'], $mysqld['password']
);
mysql_select_db($mysqld['database'], $this->link);
}
function write($sessionId, $data)
{
$sessionId = mysql_real_escape_string($sessionId, $this->link);
}
[...]
}
I use the class like this:
static function startSession($name, $mysqld)
{
[...]
$sessionHandler = new cdbsHandler($mysqld);
session_set_save_handler(
array ($sessionHandler,"open"),
array ($sessionHandler,"close"),array ($sessionHandler,"read"),
array ($sessionHandler,"write"),array ($sessionHandler,"destroy"),
array ($sessionHandler,"gc")
);
session_start();
}
Where $mysqld are the database credentials.
The static function is called every time that a user loads a page.
The error I get is:
mysql_real_escape_string(): 2 is not a valid MySQL-Link resource
(calling mysql_real_escape_string in the write function)
The credentials are correct. They are loaded from a config file and are successfully used to establish a connection a few lines after the session was started.
What seems very important to me:
I am actually able to login and data is written to the database (/session) but as soon as the login page redirects me to the home page the error mentioned above appears.
(The login page verifies a form token that is saved in the session data. But after sending that request the script isn't able to access any session data anymore.)
More Information:
The code is from a memcached session handler with database "backup".
Most likely this is what's happening (best guess based on your information):
Per the manual the session write handler is not called until after the script has ended. In many versions of PHP, all class destructors are run before calling the session write handler. Consequently, if you are closing the connection in __destruct(), then __destruct() is called before write() is - leading to an invalid connection when you try to save the session.
Related
I am facing a very strange Session problem on PHP 8(even though it doesn't work with 7.4 also, but on 7.3 it works great).
What i do is i cerated a class where i set up the Export Object and store it on Session $_SESSION['AjaxExport'][sessionid]. Now i want to load this object stored by reference on the ifram which processes the export. When i session_start it fails to load the session at all.
AjaxExporter Class
private function ExportIntro(){
while (ob_end_clean());
// remove any old ajax exports
unset($_SESSION['AjaxExport']);
$rnd = rand(1, 99999);
$this->sessionid = uniqid($rnd, true);
$_SESSION['AjaxExport'][$this->sessionid] = &$this;
Above, loads the modal where the user gets a link to start the Export. by clicking on that link i load the Below function which loads the Object from Session and start exporting by auto-reloading to export in process like (10%-20%...)
class NG_ADMIN_AJAXEXPORTER_CONTROLLER extends NG_ADMIN_BASE {
public function Export()
{
$sessionid = '';
if (!empty($_REQUEST['exportsess']) && isset($_SESSION['AjaxExport'][$_REQUEST['exportsess']])) {
$sessionid = $_REQUEST['exportsess'];
}
else {
return;
}
$exporter = &$_SESSION['AjaxExport'][$sessionid];
$exporter->sessionid = $sessionid;
$exporter->HandleToDo($_REQUEST['action']);
}
}
When the process tries to start, i get no session at all.
session_start(): Failed to decode session object. Session has been destroyed in...
Also tried to implement Seriazable on both classes but that not seam to work either because, even though the object is stored, there are no values in its properties so it's useless (even though i used reference &).
As i mentioned above, this code works just fine in php 7.3, the problems started since 7.4 and php 8
So, finally figured this out.
As a friend told me that if a class has static properties serialization may not work and i was loading Twig v3 on parent class, so i destroyed all the properties that may contained the "template" property from Twig and it worked.
Generally, cleaned my object to only contain the necessary sub-objects that needed to complete my exports.
In CakePHP 4.0
When I’m trying to do $this->Auth->setUser($user), I’m getting this error:
\cakephp\cakephp\src\Http\Session.php - Argument 1 passed to
Cake\Http\Session::_overwrite() must be of the type array protected
function _overwrite(array &$old, array $new): void
This is my code:
$user = $this->Auth->identify();
if ($user) {
$this->Auth->setUser($user);
}
When I try to var_dump($user) it contains the user details.
Please help I can’t pass in an array as the $user is not a array
This problems results from neither some previously generated output (in my case an warning) or other misconfiguration of your session.
When you look closer at the Session.php especially the write() method you will see this part of code:
if (!$this->started()) {
$this->start(); //this may result in false but cakephp ignores it here...
}
$this->_overwrite($_SESSION, $data); //will fail for no session_start() has been invoked yet
So, even if your Session has not been started, the script will process further, which results in your error message.
Therefore check if you may pass this one:
if (ini_get('session.use_cookies') && headers_sent()) {
//error headers already send
}
As long you are not passing it, you will not be able to write any data to your session
I am trying to understand PHP login system using this php-login-advanced by panique. The code snippet for register.php is:
<?php
// check for minimum PHP version
if (version_compare(PHP_VERSION, '5.3.7', '<')) {
exit('Sorry, this script does not run on a PHP version smaller than 5.3.7 !');
} else if (version_compare(PHP_VERSION, '5.5.0', '<')) {
// if you are using PHP 5.3 or PHP 5.4 you have to include the password_api_compatibility_library.php
// (this library adds the PHP 5.5 password hashing functions to older versions of PHP)
require_once('libraries/password_compatibility_library.php');
}
// include the config
require_once('config/config.php');
// include the to-be-used language, english by default. feel free to translate your project and include something else
require_once('translations/en.php');
// include the PHPMailer library
require_once('libraries/PHPMailer.php');
// load the registration class
require_once('classes/Registration.php');
// create the registration object. when this object is created, it will do all registration stuff automatically
// so this single line handles the entire registration process.
$registration = new Registration();
// showing the register view (with the registration form, and messages/errors)
include("views/register.php");
and in class Registration the constructor is:
public function __construct()
{
session_start();
// if we have such a POST request, call the registerNewUser() method
if (isset($_POST["register"])) {
$this->registerNewUser($_POST['user_name'], $_POST['user_email'], $_POST['user_password_new'], $_POST['user_password_repeat'], $_POST["captcha"]);
// if we have such a GET request, call the verifyNewUser() method
} else if (isset($_GET["id"]) && isset($_GET["verification_code"])) {
$this->verifyNewUser($_GET["id"], $_GET["verification_code"]);
}
}
On line $registration = new Registration(); a new object of type Registration is created and it's constructor is called on Server-Side. The Server calls session_start() function. If a valid Session-ID was sent by client then file corresponding to that Session-ID is loaded in $_SESSION variable or else a new Session-ID is generated and is sent to client to store that in a COOKIE to maintain the session. The rendered register.php page is sent to client. Client fills form and submits. The values of form get stored in the $_POST array on Server-Side and this time when NEW object of class Registration is created the other two lines are also executed and the user is registered.
My Question is:
Am I understanding correctly the lifetime of $_POST, $_SESSION and the Registration Object? A better explanation is most welcome.
I have a template based site that relies on persistent sessions throughout. Recently I needed to expand the session storage by defining the save handler for database storage. This works fine in the general scope of the classes within the framework however when any of the pages make an ajax request the session id get regenerated and if the form gets submitted the previous session is gone.
<?php
require_once('site-database.php');
require_once('site-config.php');
class FileSessionHandler
{
private $database;
private $life_time;
public function FileSessionHandler(){
$this->life_time = get_cfg_var("session.gc_maxlifetime");
$this->database = new database();
$this->database->newConnection(db_host,db_user_name,db_user_pass,db_user_database);
session_set_save_handler(
array(&$this,'open'),
array(&$this,'close'),
array(&$this,'read'),
array(&$this,'write'),
array(&$this,'destroy'),
array(&$this,'gc')
);
}
Please check whether you have started the session with session_start().
I altered a few variables within the php.ini file to see if something in there was causing an issue and now it works as well in the database as it did file based. Keeping the same ID.
session.cookie_secure was set to 1 in the .ini file and I changed that to 0.
My question is I am using the variable $db in my general script code and within one of my functions. It's purpose is to be the variable that is used for MySQL connections. I have a need inside a function to write some data to the database. In my script I cannot assume that an existing db connection will be open so I open a new one and close it before the function exits. Ever since doing this I am getting an error after the script runs saying the MySQL reference is bad / doesn't exist.
The only thing I can pin it to is in my core code I use the variable $db as the variable name for database connection. I also use the same variable in the function. I did not imagine this would be a problem because I do not use global in front of $db in the function. This should mean the $db I reference in my function is in the functions private scope but it seems to be closing the public $db's connection.
Any thoughts?
Fragments of my code are:
database.php
db_connect()
{
// open mysql db connection and return it;
}
db_close( &$db )
{
// close the passed by reference db connection
}
api.php
api_verify( $keyid, $userid, $key )
{
// open a new db connection
$db = db_connect();
// check for errors. if any errors are found note them in the db
// close the db
db_close($db);
}
main.php
include api.php;
include database.php;
// open a connection to the db
$db = db_connect();
// pull a list of things to process from the db and move through them one at a time
// call api_verify() on each key before working through it's data.
db_close($db)
To manage DB connections, you can create a class rather than a pair of functions. If where you say "MySQL reference", the exact error refers to a "MySQL resource", then you are using the outdated mysql extension and should switch to a more modern extension, such as PDO.
class DBConnection {
protected static $_connections = array(),
static connect($dsn) {
if (!isset(self::$_connections[$dsn])) {
$credentials = self::getCredentials();
/* Create connection. For example: */
try {
self::$_connections[$dsn][0] = new PDO($dsn, $credentials['username'], $credentials['password']);
} catch (PDOException $exc) {
// erase the frame w/ password from call trace to prevent leak.
throw new PDOException($exc->getMessage(), $exc->getCode());
}
/* End create connection example */
self::$_connections[$dsn][0]->dsn = $dsn;
}
++self::$_connections[$dsn]['count'];
return self::$_connections[$dsn][0];
}
static close($db) {
if (isset(self::$_connections[$db->dsn])) {
if (--(self::$_connections[$db->dsn]['count']) < 1) {
unset(self::$_connections[$db->dsn]);
}
}
}
static getCredentials() {
/* credentials can be stored in configuration file or script, in this method, or some other approach of your own devising */
}
}
Note that this isn't exactly OOP (it is, but only in a technical sense). The above doesn't lend itself well to unit testing. If you want a more OO approach (which will be more amenable to unit testing), extend or wrap PDO. Using dependency injection can also help with the coupling issues of the above.
I assume you are opening a connection to the same database with the same username/password at each of the places you call db_connect. When doing so,unless your db_connect explicitly specifies, that you are creating a new link, it will return an already opened link.If that link is then closed using db_close(), it will also close the other connection, since the link is the same. If you are using mysql_connect to connect to the database, it takes an argument called new link
new_link
If a second call is made to mysql_connect() with the same arguments, no new link will be established, but instead, the link identifier of the already opened link will be returned. The new_link parameter modifies this behavior and makes mysql_connect() always open a new link, even if mysql_connect() was called before with the same parameters. In SQL safe mode, this parameter is ignored.
Refer to http://php.net/manual/en/function.mysql-connect.php
I'm not sure if this is the issue you are facing. Hope it helps.
I would assume what is happening is the connect cancels out because there already is a connection, and then the close ends the current connection.
I would recommend either A) start a connection at the beginning of the file, and just know it's always there (what I do); or B) check the to see if the $db variable is set, if not then create the connection, and always end the connection at the end of the file.