PHP: Put balance of user into session variable - php

I'm currently optimizing my web site. I'm using a simple credit system that gives you access to certain pages only if you have paid for them. Right now I'm always checking in the DB if the subscription is expired. I do this for multiple pages.
Would it be a good idea to check it only once when the user logs himself in and then carry the result in a session variable?

That would be a bad idea since it's easily exploitable. A user can remain logged in for a long time, perhaps infinitely, if he wanted to. You should keep it the way it is.

Not a great idea, unless you make provisions to refresh that value in the session periodically. Otherwise, a user will be able to extend a subscription's lifetime, potentially indefinitely, by keeping a session active.

Related

Session destroy of inactive users if inactivity at browser

This is bit different scenario in session management.
I want to develop as system where if users loges in and then keep shows activity on browser his session will continue and if no activity session will destroy.
For example user logged in at abc.com after that if he access google.com , yahoo.com, etc any website his session will be continue at abc.com else session will be destroy.
Its some thing like UTM device where user logged in once and they continue use system for a fix period of time..
Please help me with your suggestions to implement solution for above?
Thank you
I am trying to do it using cron jobs and database table "logging" where i maintained entry of logged in users. In one table storing website accessed by user and accessed time, if difference of last web accessed time and current time is more than 3 minutes removing the entry of user from logging table. If there are some more options available to do it please let me know.
A session is maintained server-side and you need requests to this server to renew the session. If the user requests pages from another server, your own server will and should not be informed.
While it may or may not be possible to write some hacks with JavaScript, you would violate the privacy of the user. This hack could and surely would be used to sniff users.
If you only want to be tolerant in your session timeout, simply choose a longer timeout (extend it to an hour if necessary). Then a user has enough time to browse other sites and still keep the session on your site. All other reasons to collect user requests i can think of, are spyware related.

Ensure web app access from a single computer per user

I have developed a web application in PHP for a client. The client is now renting out access to the system to another company on a per user basis.
Is there a way to prevent the secondary company to use a single login and give it to 20 people to use at the same time? I know one can get the IP address of the client machine that is being logged in from, but this is obviously not very reliable method. The answer probably lies in a combination of cookies and tracking things in a database, but my brain gets a bit stuck thinking on how to implement a strategy here.
Create a unique session ID when a user logs in and store that in the DB. Add something to the session authentication code (run on all page visits) that checks that the user's session ID is equal to the one in the DB and if not, log them out. Then your web app will be accessible by only one user at a time.
To be completely honest though, can't you raise this issue with your client?
No way to tell if the login is shared among 20 people. You can restrict access by blocking simultaneous usage thru session cookies.
Most of all, protect yourself with a published Terms and Conditions document. Violation of which - revokes any standing agreement/contract. And sue them if you can provide evidence (logs) that they violated it.
Make sure you bind one user to one session. In that way you can generate a warning screen if somebody uses the same login with another session. You can then let the user choose to close the other session.
In that way you can make sure two users are not using the system at the same time. It's a bit like a software program you have installed on a computer: multiple users can use it, but only one at a time. This is probably fine.
If you don't want that, you should try to bind the login more firmly to the user: make sure he logs in with a personal e-mail address, and he gets notifications (if applicable) via e-mail. Also let the user set personal configurations. In that way you create extra value for users to have their own account.
If you have a login you have authentication, and you write any user id in session, make sure that only one session with this id created, if the session already exists throw error message.
The only problem you will have in case and user did not logout properly, instead of it pressing x button on browser then he will not be able to login till session s not expired.

Login System design to allow each user to be logged in on one machine at a time

How should I design a login system so that each username can only be logged on in one place at a time? I want to keep users from giving their username to someone else to login so they can avoid paying for each user.
If a user is already logged in and tries to log in on another machine should I block the 2nd login (which could be a problem if the user was logged on at work and then tried to get on at home)? Or should I allow the 2nd login and end the 1st login? Or does anyone have a better suggestion?
Some Instant Messengers (that can work only with one logged in endpoint) have a nice way of sorting out such conflicts. They show a message like
You are already logged on from <COMPUTERNAME>
(in case of a web app, that would be <IP/Browser>)
and give you a choice between
either leaving that logon alive (and not log on from the machine you're on), or
ending the existing logon (and logging on on the current machine).
This is technically the most challenging, but definitely the most friendly way - it ensures a user has only one session running, without being too obvious about it. And there is no bad blood with users unable to log in because they forgot to log out at work, etc.
Blizzard's World of Warcraft I believe implements this beautifully.
Basically, if you try to sign into the game after already being signed in, the first connection is kicked off.
This basically just entails making the session stored on the database. When you store the session data, store a username too. When a user logs in, delete any session records with that users name, and then create a new one for the person logging in.
I wouldn't suggest blocking 'new' people trying to log in, because users don't want to have to go back to another computer they have (possibly miles away) just because they forgot to log out.
There are also some other things you might have to think of. Things like sessionid hijacking. If a user just puts a cookie on their system (which is always possible) with the right sessionid, it is possible that they could use the same session on multiple computers. In which case you'd probably want to keep an IP field where you keep the data on who is currently logged on.
A typical approach to this problem is to use an
inactivity time-out period.
This system enforces a maximum number of logins per account, while allowing for the situation mentioned: a user left the office without logging out, and attempts to login from his/her home workstation.
Here are the general lines of such a system
Each account is associated with a number of concurrent logins (aka "seats") allowed (it seems the OP wished one and only one, for every account, but this could be more, and vary on an account basis).
The license manager logic keeps a list of all accounts/users currently logged-in, along with a time stamp with their "last" activity.
Before serving any page, the web application, calls the license manager (LM). The purpose is to allow the LM to update the timestamp of "last" activity, but also to deny the call in case the license was taken (more on this below)
Upon each login, the license manager logic verifies that the number of seats taken doesn't exceed the amount specified for the account.
If that is not the case, the LM simply adds the current session to the list of active session
If that is the case, the LM check for sessions in the list which are older than the time-out period. If one is found, it disables it, and grants access to the new login. If none is found, the login is denied.
upon each [explicit] log-out, the LM removes the corresponding session from the lists of active session.
Note that the general principle outlined above can have some variations, in particular:
rather than silently and systematically invalidating the [typically oldest] timed-out session, one can inform the user currently attempting to logging about this situation and let him/her decide of the need to "kill" such a session.
To avoid burdening the LM with each and every new page request, the web application can keep track on a per-session basis of the time since the session was last "refreshed" in the LM, and only call the LM if such time exceed say 1/3 of the time-out period.
Independently from the LM logic per-se, remember to keep a log of all the LM-related events (logins, logouts, inactive session "kills", refused logins...). Such logs should include the date/time, the IP address and other relevant info, and are useful when resolving issues associated with stolen passwords and such. Such logs also contain invaluable marketing, for example to find all accounts which appear to have too few seats (and could therefore purchase some ugrade), or to find at-risk accounts etc.
A few more considerations
make it easy for users to log-out (log-out button/link on most every page, at a fixed location
make it easy for users to report conflict / stolen password situation
Block the first login. If you log in at home, then in work, you don't want to be blocked, since this is a legit method. Always allow the login in the present, and drop the old ones.
I would suggest keeping track of whether each user is logged in and allowing the second login to end the first login's session.
Then allow the user whose session has ended to report possible fraudulent activity if they were kicked off in error.
Don't try to do it by counting the number of IP addresses a user has an active session from - some users may be behind load balanced proxies.
The solution is to write your own session handler - probably easiest with a database back end - and only allow one user to have one open session.
You might want to tune the session garbage collection and inactivity. You should also ensure that your system is immune from session fixation attacks.
C.
In terms of security, and this is what you're getting at, it is always a good idea to store session data in a database anyhow. Particularly if you're on a shared server.
In terms of which user to allow and which to knock off that is a matter for you to judge. I suppose you could have some secondary form of identification to make sure they are the real owner of the account. The one who actually signed up to it.
I've done this before in a web application that had the same requirement. Here's what I did:
When someone logs in, you generate a GUID and store it in your database, attached to the user. You also store this same GUID in a session cookie.
Every time a logged in user hits any page on your site, you check their cookie GUID and compare it with the GUID that is assigned to them in your database. If these GUIDs don't match, they've logged in on another machine, and you log them out from that session.
This method works really well.

Session should never expire by itself

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.

What is the best way to deal with sessions when the user may stay logged in, but a session key needs to be updated, because of another update?

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.

Categories