I am planning to create a online examination sytem in PHP. What steps could I take to restore old session, if user has accidentally closed the window?
Suppose he has already answered 49 questions out of 50 and suddenly there is power cut off (and there is no UPS) or he accidentally closes the window (even by mistake, if he clicks yes on javascript's prompt on window.unload event) and then reopens the browser, everything is lost. What could I possibly do to prevent this?
Thanks in advance :)
You would need to do one of two things:
Persist the current state on the user machine - this would have to be done via a cookie.
Persist the current state on the server.
The second option is probably more reliable, it does require that you are in constant contact with the server. It would also allow the session to resume on another machine.
The first option would probably be easier to implement.
Offer a login system where you store the progress tied to the user login, or simply use cookies that do not expire upon closing the browser (i.e. set an expiry date far in the future).
You can store the session parameters in cookie which expires after 30 day e.g.
You could save their state every time they go to the next question - if it's saved in a session, you could serialize the session and save it in the DB, related to their account.
If they open up the browser again, you can then load up the saved session, unserialize it, and continue off where they left it.
Storing the session id as a cookie with a long expire time will solve the problem but will introduce a new issue: on public or shared machines, users will have to explicitly log out (i.e. destroy the session) otherwise everyone that access the site after they quit will continue their session.
Another solution is to bind 'exam sessions' to the user, persist them on the database and continue the session if an user with a pending exam logs in. Obviously this require a bit of coding :-)
continuously save the page state into a cookie (e.g. on every form change - thus you have the state of the current page);
on submit, save the state into session (or even into database of unfinished forms) and clear it from cookie (thus you have the overall state of the exam stored server-side, so you can clear it from the cookie).
When finished, clear both cookie and session.
Of course, if there's a power outage, the cookie may not have been flushed to disk yet, but otherwise (especially if you have multiple questions on one page), the user will lose less state than if you only saved on submit.
Related
I have php login page that stores the user id in the session once the login is successful. User can navigate to different pages or can even close the page briefly and once user re-open the page, he is still logged in. However the problem is that when the user closes the page for longer time, the session get expired automatically and he has to re-enter the credentials and login again.
How can I keep the user logged in forever and log out ONLY if user decides to do so?
I would like the user to be able to close the page, turn off the pc for weeks and when he or she comes back to visit the page, he or she should be already logged in.
Sound like you need to set the cookie expiration date - as per this wikipedia article on HTTP cookies, if you do not set an expiration date for a cookie it becomes a session cookie. i.e. it expires once the browser closes.
There is no real way to specify that a cookie NEVER expires, however you can set the expiration date for some time far in the future.. i.e. in 10 years, and renew that expiration date every time the user loads a page.
setCookie( name, value, expiration )
Another alternative (which would also require some JS on your pages) would be to use the browser's internal database to store the user session id so that you can retrieve the session from your database (I assume you are using some sort of database, otherwise you will run into other issues as explained below).
If I wanted to achieve this I would probably have a piece of javascript on my page loads that checked for the existence of the session cookie, and if not, I would load the session id from the browser's database, drop the cookie, and force a page reload. There are certainly more elegant ways of achieving this, but this should give you an example of how to get this started.
Lastly, please keep in mind that if you don't use a database (i.e. Redis, Memcached, SQL), all you session information is lost when you restart your application server. This is certainly suboptimal, and you should store session information in a database if you want to have this information survive server restarts (or if you have a load balanced environment).
Hope this helps!
I have read many answers on stackoverflow, but none of them could answer my question.
Let's consider a case, where a teacher and the student use the same computer. The teacher uses it to upload marks and the student use the computer to browse the marks. Now, the cookies of the teacher are stored and accessible. The student can easily forge the cookies and present himself as a teacher to the system and create havoc.
What approach should I take to disable this? Is this only possible via sessions? Or there exists a possibility with cookies as well.
The main two suggestions I would have are:
Delete the entire session right before the user logs out or logs in. A new session should always be started when authorization level changes.
Only accept sessions ids you generate. By default PHP will accept and start a new session for any value of the session id you send it. If you receive a session id you haven't seen before, discard it and send the user a new one.
If it's not necessary to have the browser remeber the cookie between browser sessions (eg a login can be 'forgotten' if the browser window is closed), then you could NOT set the expiry date on the cookie which makes it memory-resident only.
When the user closes the web broswer, the cookie is forgotten (standard browser behaviour) so there's no link to the old session, and a new login must be provided. The old session becomes "orphaned" and (assuming you have a 'expire through inactivity' process) will be expired eventually.
If you need the browser to remember the last user even if the window was closed, then a short-but-appropriate timeout is needed - destroy the session making the cookie useless after x minutes/hours inactivity (whatever is appropriate).
I have a PHP app which requires log in, offers a log out option and force logs off users who have been inactive for X minutes.
But, if I log in, close my browser and re-open it, the $_SESSION variables still exists.
What's the general practise here? Should I want to prevent this and, if so, how?
Something in me just wants to treat closing the browser as logout ... on the one hand, it's a secure app (since it requires login) but a non-tech user might reasonably expect that if they close the whole browser then no one can see their private data. Otoh, if the browser crashes and the user restarts it, he might hope to pick up where he left off ...
What do others do?
PHP sessions work by saving a cookie to the user's browser containing the ID of the session on the server. Therefore PHP sessions work exactly like ordinary cookies do.
If you close your browser, cookies are persistent. The server doesn't know what instance of the browser the user is using, whether the browser has restarted, or even if the computer has restarted.
Providing a log-out button is the most usual practice here, but if for some reason you require the user to be logged out when the browser closes, you will have to implement something client-side, as the browser doesn't send any signal to the server when it closes.
If you are concerned about security - i.e. you are programming a highly secure application such as a payment gateway - you can follow the practice of bank websites or other payment gateways;
When the user returns to the site, they are still logged on, but when they try to perform any action that will affect the logged-in user, re-authenticate with another password screen, or ask for some memorable information.
This is a classic behavior, you can observe it on many sites, including Stack Overflow :)
Your session variable is bound to a cookie in the browser. If you want the user to really be logged off when the browser closes, sets the time of the session cookie to zero.
When you explicitly set a cookie, you can choose its expire time. When you're using session_start() to generate a session cookie, its expiration time is determined by the session.cookie_lifetime value in php.ini. If you set this to 0, session cookies will expire when the browser window is closed.
I'm using login function in my site with session.
This session of mine gets expired after a few minutes irrespective of whether the user has logged out or not.
Now what I want is that the session should only get expired when a user logs out. If a user doesn't log out his account and then comes back after 2-3 days, even then he should appear logged in.
I have found some examples where they have increased the time for a session to expire but I want that it should only expire on the log out event by the user irrespective of the time he took to log out.
How can I do that?
In particular, is this the right way to do so?
session_cache_expire(0);
session_start();
A solution that is often used, in this situation, is to:
have a not-too-long session duration: it will expire if the user is not active (that's just the way it works -- and that's better for your server if you have lots of users)
when user logs in, you set a cookie that contains what is needed for him to be recognized
if he comes back on the site (with the cookie, and without having an active session), you use the informations contained in that cookie to auto-log him in, re-creating the session at the same time.
This way:
you don't have thousands of sessions "active" with no good reason
you keep the standard way sessions work
And you have the advantage of "never being logged out", at least from the user's point of view.
Also note that with "normal" sessions, the cookie containing the session id will be deleted when the user closes his browser -- so, he will be disconnected, no matter how long the session's lifetime is.
With the solution I propose, you are the one who sets up how long the cookie should remain on the user's computer ;-)
It means, though, that when a user manually logs-out, you have to delete both his session and the cookie, of course -- so he's not immediatly re-auto-logged-in.
Of course, you have to be careful about what you set in the cookie: a cookie is not quite secure, so don't store a password in it, for instance ;-)
Actually, this way of doing things is how the "remember me" feature often works; except, here, your users will not have to check a checkbox to activate "remember me" ;-)
If you don't have the time to develop that kind of stuff, a pretty quick and dirty way is to use some Ajax request on all your pages, that will just "ping" a PHP page on the server -- this will keep the session active (but it's not quite a good way of doing things: you'll still have LOTS of sessions on the server, you'll have lots of useless requests... and it will only work as long as the user doesn't close his browser).
You can't do that with the PHP internal session handling alone. PHP will always send out the session id in a session-cookie which will expire when the user closes his browser. To achieve some sort of auto-login you'll need some accompanying code that sets a longer-lasting cookie on the user's browser and handles the recognition of these cookies and the mapping between the cookies value and the respective user account.
Please note that this greatly affects security issues so you'll have to take care of a lot of things. Please read the following on how a possible auto-login feature could be working:
Persistent Login Cookie Best Practice
Improved Persistent Login Cookie Best Practice
Do you remove your cookies while testing? Are cookies enabled? Do you destory the session somewhere in your code?
Also, see my answer to another post: Quick question about sessions in PHP which explains how to stay signed in. Just don't do a cronjob/sheduled task if you want the user to stay logged in forever.
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.