I am trying to make a login system using a series of methods and sessions. This is how it works:
User makes POST request via XHR to domain.com/api/login
Nginx does a rewrite to domain.com/api.php?request=url
File runs some validations, and if everything is good, it instantiates the target class and then uses call_user_func_array to call the target method with the newly instantiated object.
Method called is UsersController->logIn, this method runs some validations, and then calls UsersModel::Condition which in simplest terms selects the user and returns an object with the user's properties and a few methods.
Then, we run $instanceOfUserRow->LogIn(), which updates the last_logged column of that user and also instantiates the session doing $_SESSION['user_id'] = $this->user_id.
However, no matter what I try, it just will not set the session variable. I tried the following:
Naming the variable different, from user_id to identifier, to id_test, etc.
Instead of setting it in the UserRow->LogIn method, set it instead in the UsersController->logIn directly, which also didn't work
Created a session variable in my framework's main file (Called Init.php) called test.
This session variable was set successfully and behaved correctly, and the behavior was the same if I renamed it to user_id, which I thought was weird.
Created a simple function that was declared right after the session_start in the Init.php file called set_session that simply took the name and value and set a session like this: $_SESSION[$name] = $value;. This also didn't work.
At this point I have no idea what to do, I did verify that the session was active using session_status before setting any new variable. Classes are loaded using a custom autoload. I am not sure if the culprit is either how many files we are layering through (From the original request being API/login, then rewriting to api.php, then UsersController.php, then UsersModel.php and then UserRow.php) or if it could be just the fact that it is being called via call_user_func_array.
Any help or leads would really help out. Thank you.
Turns out even though nearly everything was the same, I was querying the API using HTTPS, but the request was being made from a page that was not over TLS.
So requests were being made from http://website.lan to https://website.lan/api and that caused the session to change across requests.
I'm working on a company intranet system and have a function to load a form via include while passing an url encoded array in GET format
$draftcook = urlencode(serialize($draft));
include(FORM_PATH .'newrangesubtypeform.php?draft=yes&type='.$value.'&draftcook='.$draftcook);
Unfortunately my array has gotten too long to be able to be passed via a url, I have tried many other alternatives, including setting the array into a session variable and then pulling it through in the included form but that for some reason is unable to see the session variable.
Could someone please suggest a work around for this situation, the array itself is likely to have upward of 1000 fields in it by the time the whole page is completed if that effects the solution.
Thanks
You can write into db or file a threat (id, draftcook) and pass the PK of the threat vía URL and then get the draftcook
Included code runs in the same scope as wherever you called include. I'm not even sure why you're passing this stuff info the new file; any variable that exists can be used in the include.
So you can access $draft as a regular variable already.
I'm trying to save all my session data in the Database and have this class that should handle all that and have used session_set_save_handler to set that up. Now, I don't know if it's because I don't fully understand the whole idea behind that function but the problem I'm running into is that the read() function of my Session handler class is called BEFORE the write() function is. And the reason why that is not good is because read() is trying to look for information in the database that has yet to be written into the database and of course it gets empty results.
So I decided to read the documentation behind session_set_save_handler and it looks like the only time write() is called is when the session is terminated or when PHP is closed. From my perspective this seems pretty useless... why would anyone write() or store this information at the END before they could ever get a chance to retrieve it?
What I'm trying to do is when someone creates a use session, this information is written into the database and whenever I want to check for authentication or lookup user values I want to retrieve said information.
Am I going about this all wrong?? I appreciate any clarification. If anyone needs any code to demonstrate what I'm trying to do I'll update this.
From my perspective this seems pretty useless... why would anyone write() or store this information at the END before they could ever get a chance to retrieve it?
What do you mean before they got a chance to retrieve it?
To retrieve it, the read method is called – and it is called before, so that you already have the info. But somehow this is what you are complaining about …?
Am I right in assuming that you don’t have much understanding of how PHP’s session mechanism works at all?
You call session_start on top of every script. If PHP finds a session id in the parameters passed to the script, it looks for an existing session with that id, and if it finds one, it reads the data from it. From that point on, you can work with that data – PHP has put it into the super-global array $_SESSION for you. You can access it from there, and you can put new data into it or alter the existing data.
And then, when the script ends, or session_write_close is called, the data is written back.
So of course the read function is called before the write function.
I would like to make a object, which not need to create all the time....
for example, I have a user object, and the user is created from the db, so, when the user login, I can read the user object information from the db... each user make requests, I need to create a new user object again....Even I make a singleton object...It still can "keep" the object....But I want to save the communication between the php and the db...Is there any way to keep an object instead of query the db all the time? Thank you.
Put it in $_SESSION ? That would make sense, if I read your question right
But I want to save the communication between the php and the db
Use APC or Memcached and cache the queries. Invalidate the cache whenever the User object is changed in a way that requires writing it back to the database.
This will still create a new User object on each request, but it saves you the roundtrip to the database (but not to the cache). There is no way to keep a PHP object in memory between Requests without serializing/persisting it to some other layer. PHP is shared nothing. PHP objects live for the request.
As for storing a users data in an object and storing that within a session,i think would be fine, though I would drag too much data around within the session itself. You need to get a balance however between looking constantly re-querying a data source, or using sessions. It really depends on your application and environment.
You could achieve this in two ways:
1) As Tattat says you could query the db and get the users info and save it as an object into the session $_SESSION['userObj'] = $userObj. You could then pull it back down from the session wherever you needed it e.g $user = $_SESSION['userObj'];
2) Second way is to inherit from a common php page you include on all of your pages (for now calling it common.php). Using the PHP GLOBAL varible to make it available any page that includes the commmon php file. e.g.
global $user;
$admin = db_fetch_object(db_query("SELECT * FROM user u WHERE u.user_id = '%d'", $_SESSION['admin_id']));
The varible $user would be then be accessable by your other php pages as long as you included the common.php file I mentioned before.
Hope this help dude :)
I´m having some serious trouble debugging this particular problem and I hope someone has a clue what i´m doing wrong.
I have a Custom CMS system working that uses Paragraphs as building blocks that get updated using Ajax(prototypejs) calls and functions that parse the HTML chunks in given order, clean them up and save this data in associative arrays in a Session variable.
Users log in, Session is created and I can check for this session without problem in every page I need it. The system works directly on the definitive websites, so the user can see his updates on realtime and browse the site as a normal user would do, but editing.
So, nothing new here. But here is the weird thing.
Enduser site on edit mode(admin user logged in): path "/"
After the logged status is verified, a function processes the editable content and saves an associative array to session, it also starts some javascript objects for editing every paragraph. Data is actually saved, I can use an external script to check if it´s there after this php script ends.If I load a new page(new content), Session gets updated with new data)
Admin User modifies a paragraph using an Inplaceeditor and this HTML chunk is send via Ajax to a php script that starts the named session, reads the present session data, checks if a paragraph should be modified, appended or deleted and reassigns values to existing array keys in $_SESSION. if i make a var_dump() o print_r to $_SESSION after assigning new data is there.After that the script echoes the processed html, and ajax updates the original paragraph on the calling page.
This script is in /admin/cms/...etc, that means at least 4 directories inside the root of the site.
When the script ends, I check using the same session dump script to see if data was really written/commited, but no, $_SESSION has only the original data from the calling page.
Same ID, same session name, same session_start() but no data gets written.
This whole operation is very quick, so I though it could be a speed problem, scripts ends before session_write_close can make his work.
But if I add a new key to $_SESSION array and put some data there, data gets updated and written. If i don´t output anything on this script and just process data and set session variables it also get´s updated and written.
It´s like some members of $_SESSION array are getting blocked to update.
What i did to track this error and what i´m sure i´m not doing wrong.
1.- register_globals are off of course
2.- session_name() and session_start() are always present and in the given
order. I used to have multiple
session_start() -close on a same page
to use several named sessions, but to
refine the problem this is not longer
so.
3.- I use session_write_close() after session data is processed. Also
tried without, letting php decide
when to commit data, but no luck.
4.- I`m using only cookies for SID.
5.- sessions are stored on /tmp, i can see the data getting updated.
I also tried using a custom save
handler on DB, but same problem,
"_write" got only called when no output as present.
I searched php.net, stackoverflow, google, etc for this subject. I never ask without investigation, this is my first time in many years...but it´s just so unlogical it must be something tiny a haven´t thought of.
The most weird thing is that when I just process data without output $_SESSION gets updated ok. But if i modify this script afterwards by adding the output and try again, instead of just having the new(last) value present I get the original value back, the one created by the calling page at first place, sometimes after playing around a few times! PHP can´t cache values between scripts or?I dont have globlals on.
I´m really clueless. This system worked flawless on PHP4.3, since i´m using 5.3.3 for two moths my users where caliming data where getting mixed up, so i checked and yes, there are serious problems. Today I updated to (5.3.6) and I can´t get this session values commited.
Script code called via Ajax:
<?
session_cache_limiter('nocache');
session_name("CMS_ses");
session_start();
include('../htmLawed/htmLawed.php');
include("utils_cms.php");
include("../../../php/utils_array.php");
$value=$_POST['value'];
$editorId=$_POST['editorId'];
$clase=$_POST['clase'];
$editorId=str_replace("pre","",$editorId);
$value=html_entity_decode(stripslashes($value),ENT_QUOTES);
if (strlen(trim($value))==0)
{
die();
}
$value="<div id=\"$editorId\" class=\"$clase\">$value</div>";
$newXHTML=$value;
$retorno=CMS_nuevoBloque($newXHTML,$editorId);
$_SESSION['data']['CMSeditores']=$retorno[1];
$_SESSION['data']['CMScont']=$retorno[2];
session_write_close();
print_r($retorno[0]); //Offending part...without everything works
?>
really nothing strange here....main page code is even simpler, no strange php directives, etc.
Here is the header of the caller page
include 'php/db.php';
$len=$_GET['len'];
$sec=$_GET['sec'];
$cont=$_GET['cont'];
$admfin=$_GET['admfin'];
$fecha=$_GET['fecha'];
$token=$_GET['token'];
$cur=$_GET['cur'];
$PHP_SELF=$_SERVER['PHP_SELF'];
session_cache_limiter('nocache');
session_name("CMS_ses");
session_start();
$passvar='';
unset($adm);
if ((!empty($_SESSION['cms_logged'])) and (!isset($admfin)) )
{
$nivelpermisos=$_SESSION['cms_logged_group'];
$useractual=$_SESSION['cms_logged'];
$adm=1;
}
elseif (empty($_SESSION['cms_logged']))
{
unset($useractual);
}
//.........rest of the code
UPDATE: I did late night tests and found someting i don´t understand.HElP please:
It has not only to do with Sessions but also with Mysql Querys. Same code, but instead of trying to write to $_SESSION array i made a simple update to a Innodb table using the session_id. When i Output some code, the update does get executed,(i can output the query string and no mysql_error() or notice) problems, but checking the database the row doesn´t get updated. Letting the output out if the script and Query does get commited. Only common thing is sessions are started and output is made.
I restarted Apache, etc(who knows) but no luck. Then i made something really stupid, because this is a server side thing. I changed my browser to Firefox(using safari) and everything works! Ok, recheck, back to safari, nothing works. Both running side by side, same issue. PHP is server side, how can different browsers handle code different, can a browser say to apache rollback, request not handled or call the same script twice without notice(checked safaris developer console and the script is called only once) ? Can safari resubmit data silently because it "thinks" ajax failed? I checked headers using firebug and Safaris developer tools , nothing strange but whenever i make a Ajax call with safari, the caller page reloads data(Aka conection to server...).
I really don´t understand nothing.
I had a similar problem to this (if I have understood correctly). I needed to force session data to be written (for a custom session driver) after scripts have finished running. A shutdown function can be registered which should run after scripts have finished.
Maybe this will solve (or help you to solve) your problem.
http://php.net/manual/en/function.register-shutdown-function.php
Thank's for your help. I was doing everything in the right order and still session data was not being written. Session names where necesary because sometimes we test many sites on the same domain using the same custom CMS. So, finally, after making lots of test and no luck, i found that register globals was active on this server(we never use it, code was written having this option off in mind of course), but it messes with sessions!. Switching this off made a huge change. No more problemas. I also made a custom session handler in DB, so i could track the problems in an more centralized way.
Conclussion: Never use register globals + named sessions, an complex data in sessions.
Anyway, i will give this issue more time and more tests. Ajax calls are also sometimes too fast, i had to put a sleep command so writing the session data was really done.Thanks
I am not sure but few suggestion i think may be helpful.
delete session cookies before refreshing the page for testing purposes :)
Ensure that you're not assigning any arrays with a key containing the pipe character (|). This will prevent the session data from being serialized and saved.
Do session_regenerate_id(true); many cases session_write_close doesn't seem to matter with out session_regenerate_id. or just do session_start() after session_write_close() if you are relying on SID ; and in your case i think this is what is causing problem to you as you are ending the current session every time and not re starting it for the next page. hope u get my point. Further more To Make sure data is actually flushed out to the browser use ob_end_flush();
i could not understand the connection between
$_SESSION['data']['CMSeditores']=$retorno[1];
$_SESSION['data']['CMScont']=$retorno[2];
and
$nivelpermisos=$_SESSION['cms_logged_group'];
$useractual=$_SESSION['cms_logged'];
i think you need to paste some more code where the data part is causing problem instead of admin login part.
i hope this helps you.:)
Is there any reason you're establishing the session name twice? I've had issues in the past where I would establish the session without a name, then another piece of script (not mine) was naming the session. Even at the end of the script I was able to print out the session variable, but once I went to a new page my session had been forgotten. It wasn't until I copied the name included in the 2nd script into my session call that it was solved.
Check that there's no other session names being used; also, maybe try only naming the session once, at the first call to the session?
Question: Are you calling session_start() first thing... before ANY output to the browser and before any variables are assigned?
Sounds silly but give it a try.
Also, why are you using session names? Really not necessary unless you have a lot of session variables with the same name serving different purposes and if thats the case then you need to fix that first!
I had a similar problem but it was having with ie few years back. IE manipulates the header on its own way and that causes strange php bugs that you can find in php.net archives.
#Diego Pino Navarro, please see this help page and find Safari and it's issues with php.
I also found "Safari "forget" http-authentication's logon-information".