I have a system that represents users as object. These object are initialized by reading in a database. Once the users (or objects) are created I store them in a session in order to navigate through pages without re-initiate the users from the database.
Suppose that an admin changes (let say) the users' permissions. From the edit until the session expires, a user could have higher (or lower) permissions than those declared by the admin.
How can I handle this kind of situation? Suppose I have a sessions that expires after hours or more. Should I send a request to database every n minutes to update the user objects?
The way I do it in my applications is a check on every page load.
So, permissions might be stored in a session, but you can always update those.
Let's say someone logs in and their permissions are set to full.
If you're checking on every page load and updating their session, someone can update their permissions at any time and their object will have the new permissions reflected every time they perform an action.
It doesn't matter much if they're just reading a page, but when they try to do something: submit a form, go back to home, visit a new page, or whatever, then their permissions will get updated.
Related
I'm currently using PHP sessions to keep track of user sessions, with a last-activity field for timeouts, an id field, and an account-type field. Currently, all of this information, as well as settings data, is pulled form a MySQL database and stored in the session once the user is logged in, and remains unchanged for the duration of the session.
The issue is that I wish to implement the ability for administrators to change users' account types remotely. If the user's account type is changed remotely while they're still logged in, the change in the database won't be reflected in the user's session variable.
One solution to this would be to add a logout_flag column to the users database table. When a user's account type is changed by an administrator, that user's entry in the database will have logout_flag set to 1. Then I can use a session script to check this entry on every page load, and log them out if it's set to 1.
My concern is that this would add too much overhead for the server; With hundreds of users logged in at the same time, this would amount to hundreds of MySQL queries per minute. Is this the ideal solution though?
Try with session_save_path(), with that function you can find the path where PHP saves all session files. You can delete the selected file with unlink() later.
Careful with this! If the path = the global /tmp directory. Other applications are using this directory also and you can break something.
You need to know also the session id of your user, maybe saving the token and the user id/name will help you to identify the correct session file.
At the moment, in my website several people could technically log in using the same username and password at the same time on different machines.
I want to make it so that if someone logs in then it automatically ends any session associated with that user. That way, only one instance of a particular user can be logged in at any one time.
I'm trying to figure out how to implement this. How can someone logging in and creating a new session destroy a specific session on a different machine?
Add a field called "login_token" (make it a randomly generated string) and each time the user logs in, generate a new string and update the login_token field. Also store the login_token in the session. If a users session login_token value does not match that of the one in the database then kill the session.
Currently when the user logs in my site, a (PHP) session is started and his database row is saved in his $_session. I do so because the size of user's data is small for now, and this way I do not have to ask the database for user's data every time I need it.
The problem is that, when I want to add or change something during the development and I touch the database, the session is not updated this way. The user have to logout and login again to update the session. This is good for now since the site is in development phase, but in production this is not desirable.
I wouldn't delete session files, because people are lazy and I would avoid to force them to re-login every time something change in database, and I do not want to reload the session every X minutes. My solution for now is a boolean column inside the user's table, false by default, that I set true when I change the database. Every time a session is continued, session data will be updated if that value becomes true. Anyway this way I have to do a (small) query every time an user continues a session. I do not know if this will be a problem in production.
Is there an alternative / better way to solve my problem?
If I understand the problem correctly, one way to handle this would be every time a user row in the DB is updated that user's session data could be updated as well in PHP.
If it is not the user updating the records (such as an administrator changing a user's permissions) most likely you would want to force a logout of the user. If it is the user updating the records (such as changing information in their user profile) simply updating those values in the session variables may be enough.
In both of these cases you probably also want to provide a message to the user letting them know what happened.
I've developed many login systems in PHP. Basically, for each website or application I created, it had a login scheme to create articles, upload images, edit comments e blablabla.
I've never had problems with that, except once when I created a kind of social page inside my website. There was a user bothering the other users, so I decided to delete his profile, that's why I'm here asking your help.
At the time, I was just checking the session on each page, for example:
<?php
if($_SESSION['loggedin'] === true)
{
// Keep that page
}
else
{
// redirect to login page
}
?>
Then, when I deleted his profile the session wasn't closed yet, after that the user continued annoying the other users, and I wasn't able to do anything.
So, what's the most common and best way to handle sessions on each page: Check the database each time or just check if the session is true?
I don't know whats the best way, but I do something like this:
I have an sql table with the sessions (for example userid, sessionid, expiredate, ...).
The sessionid is "saved" in a $_SESSION['cms_session'] .
If the sessionid which is in $_SESSION['cms_session'] doesn't exist in the session table, the user isn't loged in anymore.
For deleting the old sessions in the table i use crons.
What you are trying to do is have a single place where you can maintain user status and know that a change will be reflected immediately.
Checking a "user_status" field in the DB is a pretty efficient call to make on each request. This provides a single place where you know that if you deactivate a user, the changes will be reflected upon their next request. You can also do this easily without writing another set of routines to look through session variables or to create some sort of messaging system where the application announces that a user has been deactivated.
Checking the database each time a page loads is really inefficient. If all you're trying to do is kill his session, you should store sessions in memcached where the 'key' is based on the username, something like "johnsmith-session" and then on an admin page, send a message to memcached to kill that key, which should immediately log him out of your site.
If PHP is currently writing session data to disk, depending on how the data is serialized, you may be able to track down his session file on disk and delete that file, which will accomplish the same thing: the next time that user tries to load a new page, his session will be invalid and he'll be required to log in again.
Keep in mind that really persistent trouble users will often re-register a new account to continue their antics, so you'll want other means of watching for new registrations from that person.
I'm working a site where users could technically stay logged in forever, as long as they never close their browser (and therefore never get a new session key). Here's what I could see happening: a user leaves a browser open on computer A. The then use computer B, login and change their name which is stored in the session. They logout of B, but A is still logged in and still has their old name stored in the session. Therefore, their name won't be updated till the next time they logout manually or they close their browser and open it again and are logged in through the remember me function.
Name is a simple example, but in my case the subscription level of their account is stored in the session and can be changed.
How do you deal with this?
A few ideas that I have are:
After a period of 10 minutes or more, the session data get's reloaded. It might be exactly 10 minutes if the user is highly active as the function will get triggered right at the 10 minute point or it could be after 2 hours if the user leaves and comes back and then triggers the functionality.
Store as little information as possible in the session and load the rest from the DB on every page call. (I really don't like this idea.)
Use database sessions and use the same session on all the computers. I like this, but I could see it getting confusing when something like search criteria are stored in the session--the same criteria would show up on both browsers/comptuers.
For information, even such as the user's name or username/email address, store it in the session, but for other information that would heavily affect their abilities on the site, don't store it in the session and load when needed (attempt to only do it once per instance).
Are there other better methods?
--
Another option: 5. Use database session and when an update is made load the user's other sessions (just unserialize), change the relevant information and save them back to the database.
I would go either with number 1 or number 4. If you store the time of the last update of the information, you could even ask on every request whether the date has been updated.
Don't store information likely to change in the session, if you're looking at scenarios like the one you outline. Just get over your dislike of loading user data with every page - it's by far the best idea.
I'm guessing you don't want to load the data from the database because you're concerned about performance issues somehow. Before you try out any of the other solutions, you might want to test how long it takes to actually load a users data from the database, then check that against your number of users - chances are you won't see any performance problems due to loading user profiles on every page.
Regards
I'd go with option 6: only store userid and session specific stuff (search criteria) in his session and put the rest into APC/xcache (memcached if you're using multiple servers).
this way you'll only have to go to the database the first time (and after the cache expires) and you can still share any data between users sessions.
Normally you should do 2), but you don't like it.
maybe you can use sessions stored in db.
when a user change his name, put into all sessions from that user the information "refresh userdata".
on the next request the userdata is reloaded again into the session and is cached there.
this can be done be reusing your loaduserdata function which called at login.
php session_set_save_handler() - also read comments
php session_decode() - to read the username from the session to store it additionally to the sessiondata. usefull for easily to find the users sessions for updating.
[edit]
don't forget:
when you are updating all the sessions while the page is generated (between session_start and session_write_close) you changes maybe lost.