Have a session problem with application when opened in multiple tabs of a browser.
In my project a user can have multiple log in id's so he could log into the app with two id's
at the same time as two diferent users. but when they try to log in with two id in multiple
tabs of a browser. the same session of the browser is being shared and the data gets messed up.
Any insights to solve this issue?
I see a pattern in mail.yahoo.com , if i log into my mail.yahoo with one user id and try to login in
to other user id in the new tab. one of them logs out. Any idea how this could be done...
Thanks
Piecing this together from against other answers it sounds like you need multiple application streams.
That is, you have a situation where you need multiple "users" to be logged in to the application on different tabs on the same browser, same machine.
This isn't because they are different people using the machine, but rather the same person working with different personas.
It turns out, I've implemented something similar in the past myself, in order for managers to be able to "ghost" through a system as their staff members. They log in as the other user, but in a read only mode so they can see what's going on.
OK. So how to do it.
Put simply - the session isn't enough - you need more than that. The session ID is stored in a cookie on the client machine and there isn't really much you can do about the set-up - one browser = one session.
However, what you can do is split that session up with an application stream, or application context.
That is, don't store anything in the root of your session - split your session into distinct components into which you have a set-up identical to your current session.
The key for each session is then the "application stream" key. You need to pass this around in your URLs.
E.g.
Your current session may have a simple set-up:
$_SESSION['user'] = 'some username';
$_SESSION['role'] = 'power user';
Instead you store that as:
$_SESSION[0]['user'] = 'some username';
$_SESSION[0]['role'] = 'power user';
On all urls you add:
&appId=0
And whenever you reference your session you use something like:
$username = $_SESSION[ $_GET['appId'] ]['user'];
Obviously, you wrap all this up in a nice session handling class, but that's the basic idea.
If you want a link that generates a new login page with a new application stream, you simply change the appId on the link (or completely omit it and trap that in your login code).
E.g.
$sLoginLink = "<a href='/login.php?appId=" . generateNewAppStreamId() . "' target='_BLANK'>New Login Screen</a>";
As everything is still stored in the session, the whole of your application should work exactly the same - just as long as you always have the appId on every URL in the system.
I've tried to make the explanation as simple as possible - forgive me if I've used too many words.
If you want to use session then you must arrange such mechanism that only one user can be logged in same browser. At login page, check availability of session and it is already have a value than redirect your page to any logged in page like home, profile or whatever you have.
When the user logs out or logs in using a different user ID you must use session_regenerate_id() to force PHP use a different cookie for the new login.
This is actually the best practice on logout.
If you want to have two users logged in simultaneously from the same browser you have to put something in the URL to tell them apart. For example, after login, user #1 will see all the pages as http://www.example.org/1/... and user #2 will have its own customized URL (http://www.example.org/2/...). Then you need to use session_set_cookie_params() for each user with the correct value for parameter $path ('/1' for user #1, '/2' for user #2 and so on).
It's not recommended to use the user ID as customized user directory but to generate a hash from it.
Related
I have hosted 2 website, these two website use same database to populate data. eg: users - table
has user login details, both website users can access their login via this table.
Now I want to do this:
Before access both website they need to login.
My "Website A" has link call "Read More" when user click on it, that user
should be redirect to "Website B". Now I want to skip "Login" process from B website(because that user
already loged in A). How to do that,
I got mind this option, but less security:
A website read more link as
B_website/?username=abc&password=123&page=12
I guess this is not good option, what are the ways i can do this with keep high security?
No no no - do not pass the username + password in plain text in the URL!
I would recommend taking a look at how you know that the user is logged in on site A. Is there some sort of flag in your database marking this user as logged in? Could site B somehow be aware of this flag? Since your two sites share a database, this would definitely be possible.
Consider the following scenario:
User logs into site A.
A unique "login token" is generated, saved in your database and also sent to the client.
User arrives at site B.
The user sends the "login token" they previously recieved to the server.
If the login token sent by the user matches the record in the database you can skip the authentication phase and mark that user as logged into site B.
Server sessions are basically hand-designed to solve this problem. If your websites already access the same database you can utilize a PHP built-in feature, which is to create a session_handler that opens a database connection and stores your session in a database table.
I am personally a big fan of Symfony's HttpFoundation (see below). However, you can do this natively without relying on any outside libraries.
Start by creating a table (this is a MySQL table, but it should be pretty easy to adapt this:
CREATE TABLE sessions (
sess_id VARBINARY(128) NOT NULL,
data BLOB NOT NULL,
sess_expires int(11) UNSIGNED NOT NULL
) COLLATE utf8_bin, Engine=InnoDB;
Next, create a session handler session_set_save_handler(), as per PHP Documentation. Create callable functions, and assign each function like so:
Open
Create the database connection.
Close
Closes the database connection.
Read
Retrieves session from the database.
Write
Stores session in the database.
Destroy
Destroys the session.
Clean
Cleans old session data based on your system settings.
Here are some different implementations. They all should work so whichever one you find most attractive can be used as a base. Once you settle on your style, you simply copy the code in each of your client sites and it will pull a shared session!
A tutorial by Chris Shiflett is probably the most basic and accessible if you are unfamiliar with much of how this sort of thing would work.
DevShed has an object oriented approach which can probably be copied and pasted for the most part. They also do a good job explaining how to use the session in other places.
HttpFoundation - Uses locking and other mechanisms and is pretty much get-up-and-go. If you follow object oriented programming and are familiar or interested in Composer, this is an absolute breeze to get set up.
If you store the login via PHP builtin sessions and both websites use the same session_save_path, then this is quite simple to achieve. Just Pass the session id as parameter SID inside the URL. The session from Website A should then be picked up by Website B and as the user Base is shared, the session can just continue on the other website.
The read more link should be generated something like this:
Read more...
If you manually store some kind of sessionID in a cookie, you have different options. Either you always set the cookies for the domains of both websites when logging in. Like this the user is autamatically logged in on both websites, no matter on which of the two he logged in.
setcookie("SESSIONID", $session_id, time() + 86400, "/", $domain_A);
setcookie("SESSIONID", $session_id, time() + 86400, "/", $domain_B);
Another way would be to make the more link on Website A point to a special page on Website A which would then set the necessary cookie to be logged in on Website B and then do a Redirect (via 302 Header) to Website B. The link would look like:
A_website/redirect_B.php?page=12
redirect_B.php would do the work then:
setcookie("SESSIONID", $session_id, time() + 86400, "/", $domain_B);
header("Location: B_website/?page=12", true, 302);
The best method to pass the session to the other server depends on how you implemented the login. With more details about how you manage the login sessions, it would be possible to give a more precise answer.
The most secure way is to use Single Sign On through SAML.
You should use token based security i.e. when user enters his credentials in website A then website A returns a access-token,then by using this token you can validate user on both websites i.e. send access-token with every request.
This is basically how social-site login works,they also provide access-token and this is called auth protocol.
You can send through AJAX authentication data from the website "A" to the web "B" when you click on the "Read more" button: after it, you check if these data are correct. If so redirect to the page "B" (You could do this through an ajax response)
$.ajax({
type: 'post',
url: 'b.php',
data: userauth,
error: function(errors) {
console.error(errors);
},
complete: function(data) {
if(data=="correct"){ /*redirect*/ }else{ /*nothing*/ }
}
});
I think that would be an option...
¡Regards!
Best way that i would suggesgt:
1: Every time user logs in a seesion id is generated
now user below table structure
uname | password | seesion id | user ip address |isloogenid
a pwd1 sessionidcreated user looged in ip
is all paramerts are same login in user otherwise no
$seesionifdromdb
$ipfromdb
$userloggedinfromdb
$currentipwheresiteisopened
$valeofphpsessionif
if(($seesionifdromdb == $valeofphpsessionif) && ($ipfromdb == $currentipwheresiteisopened) && ($userloggedinfromdb==1)){
// here start session neede to make user logged in
}
As per your situation lets have a logical view.
sites:"Website A","website B"
Let have the general login flow If a user login to a "Website A" or "Website B",then a session will be created for that user with some session Id and some custom session variables that you will set-up to keep the user logged in to throughout the website
eg: $_SESSION['user_id'] = {some id from database};
$_SESSION['prefered_language_code']='eng';
$_SESSION['user_name'] = 'abc';
Then you are checking biapasing the login process till these variables are available in the session
eg:function checkSession(){
if($_SESSION['user_id']!=''){
return true;}
else{return false;}
}
on the other pages of both website
if(checkSession()){
return true;
}else{
//send to login page of website A or Website B respectively;
}
Something like this function you are using to check the user access for the rest of the web pages.when he log's out then you must be destroying that session variable.
So now the answer to your question is:
1)As you are managing two website and as per your comment i.e "Now I want to skip "Login" process from B website(because that user already loged in A)" it means in both the case login credentials for the user should be same.Now the solution is to achieve desired situation you should follow the same login process with same session variables (only those which are used to check login status of the user) and login checkin in both the website i.e "website A and Website B".
Then they seems to be two different websites but logically the work as single one as they are sharing the login session variable.It means if a user login in to one site then logically he is by passing the login process of other website.
2)You can set some login track field type in database to keep the track of user login
eg:loggin_token; comment some uniquely generated key or login_key
and sets these with some session variable
Now you can check the session for the session variable to keep a login check on both sites
Hope this will help as it is the most simple way to manage these
Ignore any advice sending the password.
Lix' answer with the one time token is a valid approach. If you don't want to bother with an implementation you might be interested in existing single sign-on implementations.
You must use techniques like SAML or Open ID for this.
https://github.com/onelogin/php-saml
https://github.com/openid/php-openid
I am working on a group project where my group member is working on the user part while I am working in the post ads, view ads i.e. other parts of the project. I want to create fake users which will determine the admin and user through the session . Is there a way to do this? Thank you very much.
It depends on how you are going to detect if a user is signed in, I usually create a couple of sessions depending on the results of a SQL request. If you are going down this route, you can temporarily add these sessions to the top of your files, like so:
$_SESSION['user'] = 'admin';
You can then use these session later in your code to make sure the user is signed in and to get their username ect.
I want to know how I should go about allowing users to login to multiple accounts in the same session. For example, user should be able to open a tab, logs into Account A, and opens up another tab to log into Account B. I want to also make sure that anything he does in the first tab affects account A only, but anything done on the second tab affects Account B and nothing else.
Here is more concrete example of what I am having trouble with. Let's say there is a JavaScript function called deleteList(listId)that is exposed in the global space, that is, he can call this function in the browser console. Now, this user somehow identifies the listId for a list that exists in Account B. Then, he opens up the tab where he is logged in as Account A, and uses the function to delete the list in Account B although he is on a page where he is logged in as Account A.
I know this may not be a practical or real situation, but I want to know, for the sake or learning, how to prevent this behaviour. That is, if I allow user to login to multiple accounts, how can I differentiate each connection(opened tab/window) made by user even in a same session?
Can I create a new session with each unique connection in PHP? Because what I observe is that if I open multiple tabs, they are all identified as the same session.
As far as I noticed, google handles it by argument in url. The basic idea is that you store a table of user data in $_SESSION and not single record.
Let's say you got kept in $_SESSION - username and userip after login procedure, so instead of keeping it directly in $_SESSION, you add a record to $_SESSION[] array.
$_SESSION['username'] = ...
$_SESSION['userip'] = ...
to
$_SESSION[] = array('username' => ...,'userip' => ...);
Ok so after few logins we got an array of arrays of username and userip.
The second thing is to rewrite url that it would ignore first part:
/(.*)/(.*) -> /$2?user=$1
From now on, we refer to logged user session like this:
$_SESSION[$_GET[user]][...]
That would be it. Of course you may use different rewrite rules, it is just an idea example.
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 am looking for insights into how to destroy a specific session in PHP. Through a partner website a user logs into the main website using a token and obtains a full session.
It is also possible for the partner website to call a destroy function if the user logouts from the partner website. We should then also log out our own user.
What is the best approach to this? The Zend_Session destroy method does not accept a parameter, similarly the PHP function session_destroy does neither.
I am considering two options:
Removing the session information directly from file/memcache but would prefer a "cleaner" approach than this.
Checking at every page request if this is a "token" user ; and if then check if their token was expired by maintaining a list. This adds overhead to a busy website, but might be my only option.
Or is there a third / better approach I am not seeing?
There's no need to roll-your-own session handling.
session_id() can take a parameter, the session id you want to work with.
So, when you pass the user off to the partner site, pass along their session_id (or some token, or whatever).
Then allow the partner site to hit a script like this:
kill-user-session.php
<?php
/**
* Destroy any active session identified by $_POST['sid']
*/
session_id($_POST['sid']);
session_start(); //this line may not even be necessary
session_destroy(); //destroys that session.
So when the user logs out on the partner site, the partner site POSTs the session_id (that you gave them) to your kill-user-session script, and the user's session is destroyed on your server.
Of course, you probably want to limit access to kill-user-session.php via some method or another.
If you wish to be able to 'kick' the sessions of a user(s), the only way you can do it is if you use MySQL (or someother db, sqlite even) for your session storage.
Then you can simply remove entries from the db to kill a session.
This also allows you do do things such as, 'take control' of a specific user's session and other stuff :)
See this for a very basic run through: http://www.devshed.com/c/a/MySQL/Custom-Session-Management-Using-PHP-and-MySQL/ (not the best example but good enough full example to start you).
EDIT
Also, if logging out through the partner site, another method I have used in the past (which was with O2 and other such sites) they were given a 'callback' (REST API call in most cases) which they would also need to call when the user logs out of their site.
The database solution means that the session database needs to be shared between mainwebsite and the partner site, which frequently isn't the case etc. Maybe something along these trivial lines would suffice?
<img src="mainwebsite/logout.php">
mainwebsite/logout.php:
<?php session_destroy(); ?>