Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent multiple logins in PHP website

Tags:

I want to prevent multiple logins in a php application.

First, I create login status (active, notactive) in a user table.

When user A logs in the user status will be set to 'active', and if the user logs out the status will set to 'notactive'. When another client trys to login using the same user acount, I check the user table. If the user is still active the error login will be sent to the user.

The problem occurred, if the user closes the browser the status in user table can be update because the user didn't click logout.

Do you have any suggestion about this?

like image 420
Adi Sembiring Avatar asked Nov 13 '09 08:11

Adi Sembiring


People also ask

How do I limit the number of login attempts in PHP?

php function init() { //$showInsertDat = insert login name from your login form $attempts = passwordattempt($showInsertDat); $tries = $_SESSION['login_attempts'] = $attempts; echo "Versuch: " . $tries; } function passwordattempt($insertLoginName) { session_start(); $i = 0; //if session is not set if (!

How do I stop concurrent logins?

Navigate to Product Settings → Connection → General Settings. Check the box next to Deny Concurrent Logins. Once enabled, the user will not be able to log in from another device at the same time. Other active sessions will not be affected by this change.


2 Answers

(Please note, that whilst the technique here is still somewhat valid; the PHP samples should not be copied verbatim as there are safer means of incorporating user-supplied values in a SQL query)


Instead of storing whether the user is active\inactive, it is better to store some attribute which can be checked against the user on a per-action basis; as in, every time the user tries to do something which requires authentication, it will check to see that this attribute matches before it proceeds.

I recommend you do the following;

First, create a hash to uniquely identify the user whenever they log in. I'd imagine that a sha1 of time() would be enough to avoid collisions. Whatever you choose, make sure that it is varied enough so that another user logging in will have a incredibly low chance of receiving the same hash (for example, don't hash the IP address or browser's user-agent, as these are not varied enough).

Second, store this hash in your database and in the user's session at the time of log in. Doing so will effectively 'log out' the previous user, as the hash should be different each time someone logs in.

Since we're using sessions, a cookie should be automatically placed in the user's browser which will contain a unique ID that identifies the user to his or her session data. The contents of the cookie are not really of concern.

Next, create a function called authenticateUser() or similar, which will be called at the start of every script to ensure the user is authenticated. This script should query the database, checking to see whether a user with your user's ID has a hash that matches your user's hash.

For example:

function authenticateUser($id, $hash, $databaseLink) {     # SQL     $sql = 'SELECT EXISTS(                SELECT 1                FROM `tbl_users`                WHERE `id` = \''.mysql_real_escape_string($id).'\'                AND `hash` = \''.mysql_real_escape_string($hash).'\'                LIMIT 1            );';      # Run Query     if ($query = mysql_query($sql, $databaseLink)) {         # Get the first row of the results         # Assuming 'id' is your primary key, there         # should only ever be one row anyway.                $result = mysql_fetch_row($query);          # Casting to boolean isn't strictly necessary here         # its included to indicate the mysql result should         # only ever been 1 or 0.         return (bool)($result[0]);     } else {         # Query error :(         return false;     } } 

Then, we simply pass authenticateUser() the user's ID, hash (per your session data) and a database link (for a database connection you will have to have opened earlier).

If authenticateUser() returns true, the user is authenticated. If false, the user is not OR the database is unavailable or there is an SQL error.

Please note however that this will increase your server load as a database request is sent once per page request. It is probably not all that wise to do this on giant projects where thousands of people are logging in at any given time. I'm sure someone can suggest improvements.

Also, waiting for the cookie to expire is not the best way to force people who have been inactive to log out, as you should never trust cookies. Instead, you can add in an column called last_active which you can update every time the user is authenticated. This will also increase server load, but will allow you to manually override stale log-ins by removing the hash for users who were, say, inactive for 3 hours.

like image 83
Lachlan McDonald Avatar answered Sep 22 '22 15:09

Lachlan McDonald


Here's a solution that doesn't require constant database access to work...

(which will avoid the requirement to check the session_id() against the database value every time you request/refresh a page, relieving db/server stress)...

1. On login, grab the pre-existing session_id stored in the DB for this user and do this:

session_id("the pre-existing session id in the database goes here"); session_start(); session_destroy(); 

2. Then start a new session and save this new session_id to the database, overwriting the previous one. This will logout the previous session on this user if there is one active (effectively logging out the other guy using this account).

Give it a try and let me know if that does the trick!!

like image 32
prograhammer Avatar answered Sep 18 '22 15:09

prograhammer