I'm trying to use FlashMessenger to notify another user of an event. Does anyone know if this is possible?
Something like
$flashMessenger->addMessage( array('status'=> '', 'message'=> 'Hello!'), $user);
Quoting the manual page of the FlashMessenger :
The FlashMessenger helper allows you
to pass messages that the user may
need to see on the next request. To
accomplish this, FlashMessenger uses
Zend_Session_Namespace to store
messages for future or next request
retrieval.
So, the messages are stored in session -- and a session is attached to / corresponds to a user ; the current user, actually.
The session is not meant to store data that is shared between different users -- so I would say that this component cannot be used to notify other users of an event ; not natively, at least.
A possible solution would be :
when you detect there is a message that must go to other users, store it in database (some table with a foreign key pointing to the destination user, if the destination user is a connected-user ; some table storing the message, if it can be seen by anyone).
on each page, you check in that DB table if the is a message that has to be displayed
if yes, you put it in the FlashMessenger, which will display it on next page load from the current user.
A bit tricky, and not as easy as you'd hope, I admit...
Another idea, instead of using a database, would be to use some Caching engine (like APC, memcached, ... see Zend_Cache, to avoid hitting the DB.
Have fun !
Other option would be to implemment your own session handling and store it in DB (along with username). You can then access it and alter it in any way. We've implemented this when we needed to get past some crazy restrictions (one day limited session lifetime) of hosted enviroment's session setup. It works really good and offers much more possibilities over the default implementation (like sign out all users if some specific user signs in - superadmin for example or signout user if his password is changed in admin section, etc.).
But I guess this is a bit overkill for your purposes. And Pascal's way would be good enough.
Related
I've been reading up on (mysql) triggers the last few days... specifically what I'm trying to do is figure out a good methodology for updating a user's information.
The case use for this is related to a user management system:
Take for instance a admin user updating a regular user to a manager, this user type change would then enable|disable software features on the interface.
Problem:
You won't know about this user type change unless you query the database and reset say for example the $_SESSION['user']['type'] variable, and or the user logs-in|out of the system.
Question: Is there any good methodologies to solve this headache?
I don't think mysql triggers would be ideal for this. Why? Because you will most probably end up with part of logic in php and part in mysql. It's a good thing to stay with one technology because it will be easier to maintain/debug code for you and your colleagues later.
So in your case, if you want the change of user role would take immediate action, you would have to either load user role on each script run or log out user using some flag in database that would signal that his session is not valid anymore (or you could implement your own session_set_save_handler that would save session somewhere in file where you could delete it to log out user).
It depends on your needs which solution would better fits your case.
If your roles logic is complicated and it consists of multiple roles assigned to one user as well as extra permissions assignments/excludes per user it may be better to do this check once on user log in and then just remember the result using session.
If checking for permissions on each script run isn't an issue, you can do it. But be aware, for security reasons, it may be a good practice to force user to log in again.
If the user log out could cause lose of work, you should let user log out itself and apply new permissions after next log in (you can show user a message that new permissions are awaiting log in to take effect).
So it really depends on your needs to choose if it's better to log out user, give him new permissions right away or wait until next log in.
Question: Is there any good methodologies to solve this headache?
Find good reasons not to do it!
While this might sound like a joke, i am completely serious. You have to consider:
What is the value of that feature?
Is it worth the headache cost?
What are the risks of that feature (incomplete work / system consistency)?
Do you have to change the system core?
Would you have to revalidate the system?
Are there other really great features (system improvements) waiting to be implemented?
Someone who doesn't feel comfortable answering these questions doesn't really need that feature.
Find simple alternatives:
Call the user and ask to log out.
Notify the user per email.
Provide a button for email notification.
Send email notification automatically after changing permissions.
This is no laziness. Just focus on real value.
One alternative would be to do ajax requests, with some time interval, that will update your user $_SESSION.
If you have any changes in your 'type', you can do whatever you want, like force user do re-login your application, or do nothing but update $_SESSION information.
Of course, you need to know if you really need to get this information before user logout and login next time, with updated profile.
I think storing your session into caching mechanism like Redis would give you added advantage. It is light weighted than storing session data in database. You can create clusters very easily. Click here to see sample implementation.
So once a user "type" changes, you can load the redis data cache and update it as per your wish.
I think the safest way to do this, and the one that I would choose is the "headache" way.
'regular' user A logs in and opens session A1.
'admin' user upgrades A to a 'manager'.
For now, session A1 is a valid session, but it will not grant the user 'manager' privileges.
When user A logs out and logs back into session A2, this session will now grant the user all the privileges of a 'manager, having looked up the current 'type' from the database.
Alternative that may be slightly expensive depending on your application:
Every time a user presents a session token, use the database to check against the validity of the session. If that session has invalid info (ie. the 'type' no longer matches) then force the user to log back in again.
Adding another alternative:
Don't use a MYSQL trigger, when the application caller (the admin) updates User A's 'type', it also makes a call to wherever you're caching the sessions and either (a) updates the session (inadvisable*) or (b) renders the session invalid and forces the user to log in again.
*Note that all of these solutions require the user to re-enter their credentials after they have new-found 'manager' power before they have access to the 'manager stuff'. I think this is a safer practice than updating the session without any authentication.
My recommended methodology would be to store the type of each user in the database. The problems that would arise if you decided to store the type as a session variable would be (among others):
Once the session expires, this information would be lost. Usually sessions last 30 minutes, though you could modify this to be as long as you want. However if you create a session that lasts 1 month, then anyone who has access to that users computer would be logged into the users account without needing to use any password.
You would be unable to use powerful and advances queries offered by databases (like MySQL for instance which uses SQL). If you store your information in sessions, sure you can find a way to look up each users information 1 by 1, but why reinvent the wheel? It is not easy developing a database structure from scratch, so I wouldn't recommend doing it.
Regarding your concerns on accessing a database once the information has been updated, I wouldn't say this information is as concerning as you might believe it to be. Lets imagine the following examples:
1)
If a user for instance is a manager currently and loads a website where he can do powerful actions, and right afterwards he is demoted to being a normal user, then having this information in the database would work perfectly. If the user tries to use his powers (that are no longer his), he would click a button that would send an a request to the database to confirm his type. Database queries are very fast, so speed is not an issue. I would be more concerned of the speed it takes for you to obtain information from a session variable than from the database.
2)
If the user was on a page while he was a normal user, and while on the page he became a manager, then he would be able to exercise his powers after refreshing the page. I mean if you used sessions and you wanted to have the page obtain the information automatically with something like AJAX and then update his options on the page, that would consume much more server power than a simple refresh.
To give a simple SELECT * FROM myTable WHERE id = 4 can take as little as 1 millisecond to be executed on a database. Databases have been especially designed for their speed which is why they are prefered
HOWEVER, maybe you don't have access to a database and that is why you are searching for an alternative? Well you are in luck! MySQLi is a database which only uses a file to store the information. It was especially designed for users that don't have much resources, and has many of the capabilities as MySQL would have.
Since every user has a role or type it means that the ability of viewing or editing content in your application is solidly connected to this factor. This means that the 2 basic things that your session variables should have are userID and userType which you should also store in your database
These pieces of information can be passed to $_SESSION['user'] for example as a small array where your array key can be the userID and the userType the value.
$_SESSION['user']=array($userID => $userType);
Once a user login your initial values are stored to session. In order for your application to know what userA can view or edit in your application, you basically run a comparison in your script against the userType that userA has. But to achieve what you want you basically need to re-fetch the piece of information in the beginning of every VIEW/PAGE of your application. If new userType has been assigned to userA simply show a message that he/she will log out automatically in 15 seconds (give time to read the message itself) in order for the changes to take effect. While your user sees this message you take the current session data he/she may have and save it in database, since some session variables might be (or not) available in a upgrade or downgrade of userType. By placing the comparison of the userType in the beginning of each VIEW/PAGE of your application you save yourself of the headache that a user can loose data.
If your scripts use $_SESSION['user']['type'] to know about the user's privileges, I would just change its value.
Or perhaps I didn't understand the issue ?
I know there are hundreds of these questions but what I am asking however is slightly different.
When the user logs in I would like to get all their data from each table in a database and store it in a session variable (obviously not sensative data such as encrypted password/salts etc basically data that would be useless or have no value to a hacker!!), and whilst the user uses the website the relevant data stored in the session will be used as opposed to accessing the database everytime. Moreover when the data is changed or added this will be written or added to the session file, and upon a major action such as "saving" or "loggin out" the new/changed data will be written to the database.
The reason I wish to do this is simply for efficieny, I want my application to not only be fast but less resource consuming. I am no expert on either which may explain why my idea makes no differnece or is more resource intensive.
If there is an alternative to my solution please let me know or if there is something to improve on my solution I will be glad to hear it.
Thank you.
My application is using PHP and mysql.
If any of these don't apply to your app, then please ignore. In general, I'm against using sessions as caches (especially if anything in the session is going to be written back to the DB). Here's why.
Editing the session requires a request from the user. Editing a php session outside of the request-response cycle is very difficult. So if a user Alice makes a change which affects Bob, you have no way to dirty Bob's cache
You can't assume users will log out. They may just leave so you have to deal with saving info if the session times out. Again, this is difficult outside of the request-response cycle and you can't exactly leave session files lying around forever until the user comes back (php will gc them by default)
If the user requires authentication, you're storing private information in the session. Some users may not be happy about that. More importantly, a hacker could imploy that private information to conduct a social engineering attack against the end-user.
Mallory (a hacker) might not be able to use the information you put in the session, but she can poison it (ie. cache poisoning), thereby causing all sorts of problems when you write your cache to your permanent storage. Sessions are easier to poison then something like redis or memcache.
TL;DR Lots of considerations when using a session cache. My recommendation is redis/memcache.
You can also go for local-storage in HTML5, check The Guide and THE PAST, PRESENT & FUTURE OF LOCAL STORAGE FOR WEB APPLICATIONS
Local Storage in HTML5 actually uses your browsers sqlite database that works as cookies but it stores data permanently to your browser
unless someone by force remove the data from the browser finding the data files
Or if someone remove/uninstall browser completely,
or if someone uses the application in private/incognito mode of the browser,
What you need to do
Copy the schema for required tables and for required columns and update data at a regular interval
you dont have to worry about user's state, you only have to update the complete data from the localStorage to mysql Server (and from the mysql server to localStorage if required) every time user backs to your application and keep updating the data at regular interval
Now this is turning out to be more of localStorage but I think this is one of the best solution available for me.
redis is a good solution if it is available for you (sometimes developers can't install external modules for some reason) what I would do is either go with your Session approach but with encoded/encrypted and serialized data. Or, which I really prefer is to use HTML5 data properties such as:
<someElement id="someId" data-x="HiX" data-y="Hi-Y" />
which BTW works fine with all browsers even with IE6 but with some tweaks, specially if your application uses jquery and ajax. this would really be handful.
You need to use Memcache for this kind of work. To solve the problem of keeping the updated data everywhere you can create functions for fetching the data, for example when the user logs in you, authenticate the user and after that insert all the user data into the memcache with unique keys like :-
USER_ID_USERNAME for user's username
USER_ID_NAME for user's name
etc...
Now create some more functions to fetch all this data whenever you need it. For ex
function getName($user_id){
if(Memcache::get($user_id."_name"){
return Memcache::get($user_id."_name");
} else {
//Call another function which will fetch the data from the DB and store it in the cache
}
}
You will need to create functions to fetch every kind of data related to the user. And as you said you want to update this data on some major event. You can try updating the data using CRON or something like that, because as tazer84 mentioned users may never log out.
I also use what the OP described to avoid calls to db. For example, when a user logs-in, i have a "welcome-tip" on their control panel like
Welcome, <USERS NAME HERE>
If i stored only his user_id on $_SESSION then in every pageview i would have to retrieve his information from the database just to have his name available, like SELECT user_name FROM users WHERE user_id = $_SESSION['user']['user_id'] So to avoid this, i store some of his information in $_SESSION.
Be careful! When there is a change on data, you must modify the data in db and if successfull also modify the $_SESSION.
In my example, when a user edits his name (which i also store in $_SESSION so i can use it to welcome-tip), i do something like:
If (UpdateCurrentUserData($new_data)) // this is the function that modifies the db
{
$_SESSION['user']['user_name']=$new_data['user_name']; // update session also!
}
Attention to:
session.gc_maxlifetime in your php.ini
This value says how much time the $_SESSION is protected from being erased by the garbage collector (the file that exists on your disk in which the $_SESSION data are stored)
If you set this very low, users may start getting logged-out unexpectedly if they are idle more than this amount of time because garbage collector will delete their session file too quickly
if you set this very high, you may end up with lots of unused $_SESSION files of users that have left your website a long time ago.
also i must add that gc_maxlifetime works together with session.gc_probability where in general you need lower probability for high-traffic websites and bigger probability for lower traffic since for each pageview there is a session.gc_probability that garbage collector will be activated.
A nice more detailed explanation here http://www.appnovation.com/blog/session-garbage-collection-php
I know this sounds stupid but ....
If ur data is not sensitive the best way to make it accessible faster is to store it in hidden variables inside the forms itself. You can save comma separated or values in an array.
I started writing a web application that stores certain user information in the $_SESSION variable. Usual stuff - user_id, username etc.
I then started using the variables to store certain navigation information. For instance, $_SESSION['organisation_id'] so that wherever the user is in the application, I can easily add 'organisation_id' to any table without having to parse 'organisation_id' across every page request (eg. index.php?organisation_id=456&var2=6 or anotherpage.php?organisation_id=456& etc)
All hunky dory until a user opens a new tab and starts navigating to another organisation so hence creating a new $_SESSION['organisation_id'] value and creating an epic fail on the original tab.
The only solution I can think of is to go back to putting organisation_id into every form and navigation element within the application but yeesh, I'm thinking there must be a more elegant solution.
Normally, I find everything I need on StackOverflow but the answer to this question still eludes me!
"The only solution i can think of is to go back to putting organisation_id into every form and navigation element within the application but yeesh, i'm thinking there must be a more elegant solution."
No there isn't.
Maybe you can check if $_SESSION['organisation_id'] exist, and if so you can write new variable in session with different name, and so one.
Currently there is no way to solve the problem. But to avoid a similar task in the future, I would suggest split up all your files into different includes.
So even if you have to add a couple of variables to the entire site, you could modify 1 file and get it done than doing the whole thing again.
I think this is a logic problem. The session represents a state for the user. This is because HTTP is a stateless protocol in it's essence (it don't know who is who, just undersdants requests and responses).
So the organization_id is a state. If a user can login to just one organization, you just store this in the session var like you did and use it. If the user logs out and in again with another organization_id, it makes sense that only the last one remain available.
If your application has to support multiple organization_id's, you should reflect that logic in your session handling, saving an array of organization ids for instance (instead of just one). But then you have to change your application to allow the user to navigate from organization to organization, etc. There's no point in letting the user be in two organizations at once if the screen just shows one of them.
you can store the value into session during onblur of that username, etc and you can get it before you clicking the next tab
(i.e) using Jquery/Javascript u can get that value of username, etc while onblur and store it in session.
You can resolve this by simply moving the data you currently put into the $_SESSION array into a sub-array within $_SESSION, so that you can store multiple sets of data at once in the session.
It would end up looking a bit like this:
$_SESSION[organisations] = array(
'456' => array('organisationID'=>456, 'otherdata'=>'blah'),
'678' => array('organisationID'=>678, 'otherdata'=>'blah'),
...etc...
);
This will allow you to keep the data for multiple orgs in the session data at once, so you don't have to load all the data every time.
But yes, you will need to send the relevant organisationID with every request, so that your code knows which element of the session data to work with. You can't really work around that. Every request will need tell PHP which orgID to work with.
The down-sides here are that by storing all that data in the session, you're using a lot more memory for your session data, so if there's a chance that the user will browse a lot of organisations during a session, I would advise limiting the size of $_SESSION by dropping data that hasn't been used for a while.
The other down-side is that if this is a multi-user system, storing the data in session means that it will be unaware of any updates made by other users. If you were to load the data fresh from the database on every request, yes it would create more work for the DB, but it would ensure that the data given to the user was always up-to-date.
I'm currently building a web application that uses a combination of OpenID and uname/pw authentication to authenticate users. Users are supplied a PHP session when they login successfully, and some information about their account (email address, usergroup, blah blah) is written to that session.
However, there may be a need for me or someone else as an administrator to update a users details (or to ban them immediately if they're very naughty). I'm hesitant to use a killsession tag like this (pseudocode):
session_start();
mysql_start(connection_stuff);
if (mysql_query("SELECT FROM users WHERE uid = '$_SESSION['uid']' AND KillSession = true")) { Kill session, force reauthentication };
However, doing it like this has two flaws:
We have to query the database every time someone loads a page to see if something changed
We gotta log the user out which just annoys him (or reload all of his session variables, which doesn't seem efficient)
Is there some way I can modify a user's session while they're still in it without having to resort to forcing them to login again? Some people seem to suggest in this stackoverflow thread using session_id to change to the user and then fiddle with their variables, but that seems like a shoehorn way of doing it. Thanks in advance!
I think instead of storing that stuff along with the session, it should be kept (and cached) separately. That way you avoid data duplication and the issue you're running into right now.
If an admin needs to kill the session, just DELETE it from the table.
Even though you express concerns about having to query the database on every page load, my guess is that it most likely does not affect performance noticeably. If the website is database driven in the first place, them it's just a matter of a single more query. I'd actually say that moving the entire session handling to the database (store session variables in a table) can make your system better in terms on flexibility. It will be much easier to deploy your system on multiple servers and do proper load balancing if that is someting you think will become necessary at son point. That is how the bigger CMS systems handle their sessions. My advise is, in other words, to stick with the extra query and actually consider to move session state to the database.
I've got a php application and I'm saving the session variables for the user using $_SESSION itself. Is there any particular advantage of storing it in a database?
I'm looking for a reliable / well-researched article which talks more about this. I havent been able to locate anything yet.
The advantage you have of storing it in a database is that the data exists as long as you want it to exist.
Your browser will destroy the session according to how it is setup, which makes it a bit unreliable. I can't however find an article on this yet but this is what I use as a convention for a situation like this.
Any data that needs to be stored long term, like user details and activity I store in a database. Any data that is only relevant to the current workspace, like logging into a site and posting a few comments etc. can be stored in the session. For instance I store user authentication details in a session to constantly check whether the user is logged in or not and whether to redirect him/her to the correct page.
This works wonders when checking access rights throughout your application.
For me its much safer to store user details in a database because it cannot be publically accessed like the $_SESSION.
Please disagree with me if you want to though.
I would say storing in database is better.Because
When you are hosting your site with a shared host
PHP uses the same path for storing sessions for all the users,somewhere that is not in your folders.
You can track the users and their status easily.
For application that are running on multiple servers, you can store
all the session data in one database.
This article may help.
Well this is a question for the ages. Personally from what I have learned in my time. Unless your site starts booming on a massively large scale where you need to start using multiple servers for various aspects of the system such as load balancing where you have many mirror systems running. Or need to improve performance a little for an over populated system the benefits of using DB related sessions or File based sessions really isn't any different.. Grant it I could be wrong this is merely my own personal perception off my own experiences. Just like you Ive never really found any articles, posts, other that really put either to the test side by side hell I don't even think I have found anything that really puts either to the test stand alone for that matter. Personally I just go with what ever the need is (or desire of my client) usually I just stick to native sessions file based.
I hear they can be spoofed, but have seen no proof to that notion to date. So other than that potential I stick with file based. Unless I am using a system like code igniter then sessions seem to handle better DB driven with it rather than not.
At some point in time you're going to have to store something in a session. Whether it's all the session variables or just the ID of a row in a sessions table. That being the case it would be fairly easy to alter the ID stored in a badly encrypted session and hijack a different session.
Consider this:
Full Session Option. This has the User ID, Username and an encrypted and hashed password stored so that every time a page is called it verifies my login. To hijack someone else's session I'd have to know their User ID, Username and Password Hash and be able to overcome the sessions inherent encryption.
Session + DB Option. This just has a Session ID stored that references a row in a database. All I have to do to change the session I want is to break the encryption on the session and say add one to the Session ID. I'd then be authenticated as the user that logged in after me.
You could store login details in a session and then any none login related data in a session table if you have a lot of extra information but then again you might as well just remove the need for an extra table and extract the data from whatever relevant tables you need.
From my short experience, you should store in $_SESSION only data that you will NOT need to be refreshed in all sessions opened by a unique user in different devices.
(mobile/desktop/etc.)
In other words, data that you are sure will never change like a userID.
For example, I had stored the user profile picture path into
$_SESSION and it led to a strange User Experience. When changing the
profile picture in a desktop, it did not refresh the profile picture
for the user on his mobile. Other users saw the new picture though.
Indeed, the path was refreshed into the DB but not in the $_SESSION.
Login-out and Login-in would not change anything.
Remember that the default behavior is that $_SESSION passed with cookie will be different for each browser even if this is the same user logged in. You will have to do a session_destroy() to avoid being stuck with old data.
Very temporary data may be stored in $_SESSION as well I guess.
NB: the basic need of global session, out of these arguments, is to have variables available globally