Forum Moderators: coopster
#Reward for answering this post:
if ('Arizona' == $location) {
$reward = 'Taco lunch and a blue slushy';
}
else {
$reward = 'A billion thanks';
}
//I know... ternary operator is more efficient :o) Ok, I don't live in a van down by the river, so enough of the motivational speech. The following post is closely related to my problem/question, but it's closed for replies:
[webmasterworld.com...]
So I'll restate the problem here in engineering format:
-------------------
GIVEN
I run a PHP, mySQL subscription based website. I use session vars (they work, but I am no "session-master") to grant access for paid customers who pass the mySQL username/password validation. One user can login as many times as they want simultaneously. :(
FIND
A method to prevent more than one simultaneous login per account.
SOLUTION
A) In an ideal world, the solution would follow the KISS (keep it simple stupid) mentality: when they login, write status "1" to the db. When they logout, write status "0". Disallow logins with prexisting status "1"s. Obviously this is not the ideal world as people seldom officially "logout".
B)?
-------------------
Refer to code above to determine your reward, and thanks so much for your time.
PS: I'm not terribly intersted in having a pop-up box that nags, "do you want to stay logged in?". This isn't a bank. ;)
This way only one person can be logged in at one time from one browser on one machine. If this seems too restrictive you can modify the instructions to allow 2 logins for example.
People who shared their login will be in trouble since they will keep getting 'kicked off' by others logging in with their name. You can provide a reset password link that requires email verification so the rightful owner can reset their pw.
Great response! Thanks a ton! This seems like a perfect solution for me. And although I haven't yet implemented it, I'll work out the hurdles I had/have in an attempt to help the next person checking out this post.
If they log in successfuly then save the session id (which is the value stored in the session cookie) in the db in the users table.
At first I didn't know how to retrieve this variable. A quick look in the php manual showed me it is accessible thru the function session_id() [us3.php.net]. Something like:
$this_session = session_id();
For every page they request check that their session id matches the one in the users table.
This is the part of which I was most "afraid." I think I have an implementation, but stay tuned... I'd like to test it b4 I post. Plus I'm hungry.
I read that "They should be of constant length, either 128 bits (32 characters) or 160 bits (40 characters) depending on whether MD5 or SHA1 is used to generate them respectively."
But how do I determine MD5 or SHA1?
[us2.php.net...]
[us2.php.net...]
Oh just remember these are one-way hashes so when you want to compare the current session id to the one that's stored, you need to md5/sha1 the current session id and then compare it.
--Nick
Depends on how much security you really need. If this is banking software that allows users to log in and check statements then more is needed as opposed to something on an intranet that uses NTFS permissions and DNS authentication and only like 5 people are going to use....but, that's your decision to make I suppose.
--Nick
Physcis, thanks especially for coming up with such a simple way to prevent membership fraud. I have the solution up and running on a site, and it's working like a charm. I'll post my code. Hopefully someone in the future can benefit:
Note: I pasted the below code into my header file, which is an include on every page of my site. That way, everytime a logged in user clicks on a link, it runs (as physics recommended). Pretty cool...
#Prevent Membership Fraud
//check if someone is logged in
if (isset($_SESSION['user_id'])) {
//connect to your db
require('../../../connect.php');
/*build query using hirer_id and current_session_id, get count. If query comes back with a 1, it means there is a match. A match is good because it means no one else logged in during their session. On the other hand, a 0 indicates that no match, meaning someone else logged in simultaneously. Zeros get the boot of death.*/
$result = mysql_query('SELECT COUNT(*) FROM user WHERE user_id='.$_SESSION['user_id']." AND session_id='".mysql_real_escape_string(md5(session_id()))."'");
$login_status = mysql_result($result,0,0);
//recall 1 is good, 0 is bad
if (0 == $login_status) {
//give them the boot
//this is copied from my logout script
$_SESSION = array(); //destroy the variables
session_destroy(); //destroy the session itself
setcookie(session_name(), '', time()-300, '/', '', 0); //destroy the cookie
echo 'Hey, someone else logged in using your account info which means you get the boot.';
exit();
}
}
When I started this solution I was concerned about page performance, speed, due to the fact that everytime someone clicks on a link, the db gets hit up with a query. So I tried to design a speedy query. I believe COUNT(*) does the trick as it returns a simple integer instead of a row of data.
Couldn't of done it without you guys. Thanks a ton!