Does all AMFPHP 2.1 requests starts a new session? - php

I was trying to minimize the db hits by storing data in session when the session starts and then return the data from the session for the subsequent requests. But It looks like it is not working as I expected
See test remote method below
update: added session_start() which I missed to copy
Main.php - Service class
class Main{
public function amfRequest(){
session_start();
$test = new Test();
return $test->testSession();
}
}
Test.php
class Test(){
public function testSession(){
if (!isset($_SESSION['test'])){
return "setting sesion variable";
$_SESSION['test'] = "all set!";
}else{
return "getting session variable";
}
}
}
Expected result
1st run - return setting sesion variable
subsequent runs - return getting session variable
But it is always returns setting sesion variable
Does AMF PHP destroys the session every time I request? if so, how to handle sessions then?

Answer is NO. The results I was getting because the session was destroyed somewhere else in the code, thus I was always getting isset($_SESSION['test']) as false.

Basic codding info. Workflow breaks in return. so $_SESSION['test'] = "all set!"; newer gets call.

Related

Not able to set user in Auth using setUser in CakePHP 4

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

Mediawiki SessionProvider $_SESSION variable is empty

I'm trying to implement a SessionProvider auth plugin for a mediawiki install.
I'm trying to integrate with an existing auth system that uses $_SESSION to indicate that a user is logged in, however any method I try, the resulting $_SESSION variable that I get inside the class' provideSessionInfo function is empty.
Previously this was done with a onUserLoadFromSession hook (that contained the bulk of the logic code below), but the update appears to have broken actually looking at the existing $_SESSION:
public function provideSessionInfo(WebRequest $request)
{
// $_SESSION is hidden away per-request, but $request->getSession likes to call this function (yay infinite loops)
if (!isset($_SESSION['memberid'])) {
return null;
}
$memberid = $_SESSION['memberid'];
$mr_user = MyRadio_User::getInstance($memberid);
$user = User::newFromName($memberid);
$dbr = wfGetDB(DB_REPLICA);
$s = $dbr->selectRow('user', ['user_id'], ['user_name' => $memberid]);
if ($s === false) {
return null;
} else {
$user->mName = $memberid;
$user->mId = $user->idForName();
$user->loadFromDatabase();
$user->saveSettings();
}
if ($mr_user->hasAuth(AUTH_WIKIADMIN) && !in_array('sysop', $user->getGroups())) {
$user->addGroup('sysop');
}
$user->mTouched = wfTimestampnow();
return new SessionInfo(SessionInfo::MAX_PRIORITY, [
'provider' => $this,
'persisted' => true,
'userInfo' => UserInfo::newFromUser($user, true),
]);
}
If I hardcode $memberid, the function and the session provider works fine, but I just can't seem to find a way to transfer the session from one PHP "application" to another.
Adding debugging shows the PHPSESSID variable still set in the cookie, but for whatever reason it can't be pulled out into an actual session object. I've tried various session_start() style methods to no effect.
I feel like I'm missing something obvious, but the documentation for this stuff is just a basic wiki page and the raw generated doxygen.
Session handling is not a good way of cross-application communication. MediaWiki uses its own session handling, which means there is no connection between $_SESSION in MediaWiki and $_SESSION in your application at all. The first will be populated from MediaWiki's object cache (as configured by $wgSessionCacheType), the other from PHP session files or whatever.
If you really do not have a better way to pass data, you'll have to write a custom access class which can be called by your provider, which will save the current session handler, install a null session handler (which restores PHP's native session handling which will hopefully be interoperable with the other application), start the session, fetch the session data, restore the original session handler, and probably start the session again.

Laravel 5.1 Cookie Issue

I'm trying to set a cookie when I load a view:
$cookie = Cookie::make('mycookie', $myval, 43200);
$view = view('myview')->with($data);
return Response::make($view)->withCookie($cookie);
And read the cookie on a later request:
if (Cookie::has('mycookie')) {
//do something
}
The cookie never gets set... where am I going wrong?
This works to reliably set a cookie with Laravel:
use Illuminate\Http\Request;
use Illuminate\Contracts\Cookie\Factory;
class MyClass
{
public function handle(Request $request, Factory $cookie)
{
$cookie->queue($cookie->make('myCookie', $request->someVal, 129600));
return redirect('/myPage');
}
}
You can create cookie like following
$view = view('myview')->with($data);
$response = new Illuminate\Http\Response($view);
return $response->withCookie(cookie('name', 'value', $minutes));
Or you can queue the cookie like below, and it will be sent with next request,
Cookie::queue('name', 'value');
return response('Hello World');
Read More
A possible cause of your missing cookie problem could be that if you have a invalid Blade directive the page will display normally however any cookies set will not be persisted.
I encountered this problem as I had included #script in my blade template rather than #section('script')
I suspect the reason the cookies does get set is that the bad directive causes an error in the compiled php code that the view gets cached as and so the processing crashes before the cookie is transferred.

PHP Save Session when using session_write_close();

I've one page where i do a long polling i've to use at the begin of this page this
session_start();
session_write_close();
Because :
to prevent concurrent writes only one script may operate on a session at any time
So if i do not and the long polling is running the user will not be able to load another page.
So accessing to my data in session from this polling page is possible but at some point in my script i've to save my session back to the server because i made some change in it.
What's the way to do it?
That will be very nice it'll be a way to do something like
session_write_open();
//do stuff
session_write_close();
But the session_write_open() doesn't exist!
Thanks
Before you make some change to the session, call session_start again. Make the changes, and if you still do not want to exit call session_write_close once more. You can do this as many times as you like.
The previous solution will create a session ids and cookies... I wouldn't use it as is:
Session is created every time you call session_start(). If you want
to avoid multiple cookie, write better code. Multiple session_start()
especially for the same names in the same script seems like a really
bad idea.
see here : https://bugs.php.net/bug.php?id=38104
I am looking for a solution right now too and I can't find one. I agree with those who say this is a "bug".
You should be able to reopen a php session, but as you said session_write_open() does not exist...
I found a workaround in the above thread. It involves sending a header specifying manually the session id's cookie after processing the request. Luckily enough I am working with a home-brewed Front Controller that works so that no sub-controller will ever send data on its own.
In a nutshell, it works perfectly in my case. To use this you might just have to use ob_start() and ob_get_clean(). Here's the magic line:
if (SID) header('Set-Cookie: '.SID.'; path=/', true);
EDIT : see CMCDragonkai's answer below, seems good!?
All of the answers here seem to be saying to use the session methods in ways that they were clearly not intended to be used...namely calling session_start() more than once.
The PHP website offers an example SessionHandlerInterface implementation that will work just like existing sessions but without locking the file. Just implementing their example interface fixed my locking issue to allow for concurrent connections on the same session without limiting my ability to add vars to the session. To prevent some race conditions, since the app's session isn't fully stateless, I did have to make a way to save the session mid-request without closing it so that important changes could save immediately after change and less important session vars could just save at the end of the request. See the below example for usage:
Session::start();
echo("<pre>Vars Stored in Session Were:\n");print_r($_SESSION);echo("</pre>");
$_SESSION['one'] = 'one';
$_SESSION['two'] = 'two';
//save won't close session and subsequent request will show 'three'
Session::save();
$_SESSION['three'] = 'three';
If you replace that Session::start() with session_start() and Session::save() with session_write_close(), you'll notice that subsequent requests will never print out the third variable...it will be lost. However, using the SessionHandler (below), no data is lost.
The OOP implementation requires PHP 5.4+. However, you can provide individual callback methods in older versions of PHP. See docs.
namespace {
class Session implements SessionHandlerInterface {
/** #var Session */
private static $_instance;
private $savePath;
public static function start() {
if( empty(self::$_instance) ) {
self::$_instance = new self();
session_set_save_handler(self::$_instance,true);
session_start();
}
}
public static function save() {
if( empty(self::$_instance) ) {
throw new \Exception("You cannot save a session before starting the session");
}
self::$_instance->write(session_id(),session_encode());
}
public function open($savePath, $sessionName) {
$this->savePath = $savePath;
if (!is_dir($this->savePath)) {
mkdir($this->savePath, 0777);
}
return true;
}
public function close() {
return true;
}
public function read($id) {
return (string)#file_get_contents("$this->savePath/sess_$id");
}
public function write($id, $data) {
return file_put_contents("$this->savePath/sess_$id", $data) === false ? false : true;
}
public function destroy($id) {
$file = "$this->savePath/sess_$id";
if (file_exists($file)) {
unlink($file);
}
return true;
}
public function gc($maxlifetime) {
foreach (glob("$this->savePath/sess_*") as $file) {
if (filemtime($file) + $maxlifetime < time() && file_exists($file)) {
unlink($file);
}
}
return true;
}
}
The other answers here present pretty good solutions. As mentioned by #Jon, the trick is to call session_start() again before you want to make changes. Then, when you are done making changes, call session_write_close() again.
As mentioned by #Armel Larcier, the problem with this is that PHP attempts to generate new headers and will likely generate warnings (e.g. if you've already written non-header data to the client). Of course, you can simply prefix the session_start() with "#" (#session_start()), but there's a better approach.
Another Stack Overflow question, provided by #VolkerK reveals the best answer:
session_start(); // first session_start
...
session_write_close();
...
ini_set('session.use_only_cookies', false);
ini_set('session.use_cookies', false);
//ini_set('session.use_trans_sid', false); //May be necessary in some situations
ini_set('session.cache_limiter', null);
session_start(); // second session_start
This prevents PHP from attempting to send the headers again. You could even write a helper function to wrap the ini_set() functions to make this a bit more convenient:
function session_reopen() {
ini_set('session.use_only_cookies', false);
ini_set('session.use_cookies', false);
//ini_set('session.use_trans_sid', false); //May be necessary in some situations
ini_set('session.cache_limiter', null);
session_start(); //Reopen the (previously closed) session for writing.
}
Original related SO question/answer: https://stackoverflow.com/a/12315542/114558
After testing out Armel Larcier's work around. Here's my proposed solution to this problem:
ob_start();
session_start();
session_write_close();
session_start();
session_write_close();
session_start();
session_write_close();
session_start();
session_write_close();
if(SID){
$headers = array_unique(headers_list());
$cookie_strings = array();
foreach($headers as $header){
if(preg_match('/^Set-Cookie: (.+)/', $header, $matches)){
$cookie_strings[] = $matches[1];
}
}
header_remove('Set-Cookie');
foreach($cookie_strings as $cookie){
header('Set-Cookie: ' . $cookie, false);
}
}
ob_flush();
This will preserve any cookies that were created prior to working with sessions.
BTW, you may wish to register the above code as function for register_shutdown_function. Make sure to run ob_start() before the function, and ob_flush() inside the function.

MySQL connection fails because of invalid link resource

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.

Categories