6

I heard the best method to share session across multiple domains on same server is to use custom php session handler. (ie, domain name different like abc.com, xyz.com but single application.)

But after i tried it, even custom php session handler that using SAME DATABASE ON 1 SERVER can't share session, when i tried to read cookie value from different domain.

Here's my custom session handler, Please kindly check or fix if something missing here. because i've tried it for a week now. can't get it to work

P.S. To get previous session id, i use link such as: newdomain.com/?ssid=[SESSION_ID]


SESSION_INCLUDE.PHP

<?php 

// config 
$m_host = "localhost"; //MySQL Host 
$m_user = "db_user"; //MySQL User 
$m_pass = "db_pass"; //MySQL Pass 
$m_db   = "db_name"; //MySQL Database
$table  = "sess_data";

$session_expire = 600; // Session expire time, in seconds (minutes * 60 = seconds) 

$gc_probability = 100; // Probability that the garbage collection function will be called. 50% chance by default 

ini_set("session.gc_probability",$gc_probability); 

/* Open function; Opens/starts session 

   Opens a connection to the database and stays open until specifically closed 
   This function is called first and with each page load */ 

function open ($s,$n) // do not modify function parameters 
{ 
  global $session_connection, $m_host, $m_user, $m_pass, $m_db; 
  $session_connection = mysql_pconnect($m_host,$m_user,$m_pass); 
  mysql_select_db($m_db,$session_connection); 
  return true; 
} 

/* Read function; downloads data from repository to current session 

   Queries the mysql database, unencrypts data, and returns it. 
   This function is called after 'open' with each page load. */ 
function read ($id) // do not modify function parameters 
{ 
  global $session_connection,$session_read,$table; 
  $query = "SELECT data FROM `$table` WHERE id=\"{$id}\""; 
  $res = mysql_query($query,$session_connection); 
  if(mysql_num_rows($res) != 1) return ""; // must return string, not 'false' 
  else 
  { 
    $session_read = mysql_fetch_assoc($res); 
    $session_read["data"] = base64_decode($session_read["data"]); 
    return $session_read["data"]; 
  } 
} 
function write ($id,$data) // do not modify function parameters 
{ 
  if(!$data) { return false; } 
  global $session_connection, $session_read, $session_expire, $table; 
  $expire = time() + $session_expire; 
  $data = mysql_real_escape_string(base64_encode($data)); 
  if($session_read) $query = "UPDATE `$table` SET data=\"{$data}\", expire=\"{$expire}\" WHERE id=\"{$id}\""; 
  else $query = "INSERT INTO sess_data SET id=\"{$id}\", data=\"{$data}\", expire=\"{$expire}\""; 
  mysql_query($query,$session_connection); 
  return true; 
} 
function close () 
{ 
  global $session_connection; 
  mysql_close($session_connection); 
  return true; 
} 
function destroy ($id) // do not modify function parameters 
{ 
  global $session_connection,$table; 
  $query = "DELETE FROM `$table` WHERE id=\"{$id}\""; 
  mysql_query($query,$session_connection); 
  return true; 
}
function gc ($expire) 
{ 
  global $session_connection,$table; 
  $query = "DELETE FROM `$table` WHERE expire < ".time(); 
  mysql_query($query,$session_connection); 
}
// Set custom handlers 
session_set_save_handler ("open", "close", "read", "write", "destroy", "gc"); 

// Start session 
session_start(); 
?>




MySQL Database Description

create table sess_data (
id2 int not null auto_increment,
id text not null,
data text,
expire int not null,
primary key(id2)
);
PHP Newbie
  • 63
  • 1
  • 1
  • 4
  • I thing the answer lies here: http://stackoverflow.com/questions/9317595/maintaining-session-variables-across-subdomains – haldyr Nov 08 '12 at 09:16

5 Answers5

11

You can't read cookies from one domain in another domain. That's a security thing implemented in the browser. Using a database for sessions allows you to have multiple servers share sessions on the same domain, but does not allow for multiple domains on the same server to share sessions.

If you want to share sessions between domains, you would need to implement some sort of session transfer method when you switch domains. The simplest way to do this would involve passing the session id as a GET parameter from a page on one domain to a page on the other. Then, on the other domain, you would pick up the session id and create a new session using that ID.

While that is a simple way to do it, it isn't very secure and allows for session hijacking. A better way would be to use the database to create a record with the session id in it, set a short timeout on it, and pass the ID of that record to the other domain. The other domain would then pick up the record from the database and create a session with it. If the record in the database is past it's expiration, it wouldn't pick up the session. This would provide better protection against session hijacking.

Eric Petroelje
  • 59,820
  • 9
  • 127
  • 177
  • If you want to share sessions between domains, you would need to implement some sort of session transfer method when you switch domains. yes, i've used this method to get the previous session id.. it's not working.. if new domain use same id, it will delete previous domain's id – PHP Newbie Jan 21 '11 at 14:00
  • @Eric Petroelje, your solution is great, Thank – Frank Myat Thu Nov 27 '12 at 02:46
1

This is the purpose of session_name(). Assign a different name to each application's session to avoid collisions between $_SESSION keys. The name will be used as the session cookie's name so although both session cookies will be passed to both applications, only the one matching the application's session_name() will be used to populate $_SESSION.

// App 1
session_name('app1');
session_start();

// App 2
session_name('app2');
session_start();
hamidso
  • 17
  • 6
0

I was wondering if anyone could give some suggestions on my method for sharing sessions between domains on same server (same cookie storage folder).

In each pages HEAD tag on all my sites, I call the following PHP code

if(!isset($_SESSION['sso'])) {
    require_once('database.php');
    $sites = array('http://site1', 'http://site2');
    session_regenerate_id(); //Make new session id that will be shared

    $session_id = session_id();
    foreach($sites as $site) {
       if($site != CURRENT_SITE) {
          $sesh_key = md5(SALT.$site.$session_id);
          $database->insertSessionId($sesh_key, $session_id);
          $url = sprintf('%s/sso_set.php?k=%s', $site, $sesh_key);
          echo('<link type="text/css" rel="stylesheet" href="'.$url.'" />');
       }
    }
    $_SESSION['sso'] = 'SET';
}

Then on each site I have a file called 'sso_set.php' which contains

<?php
session_start();
if(!isset($_SESSION['sso'])) {
    require_once('database.php');
    $key = $_GET['k'];
    $session_id = $database->getSessionId($key);
    if($session_id) {
        session_destroy();
        session_id($session_id);
        session_start();
        $database->deleteSessionId($key);
        $_SESSION['sso'] = 'SET';
    }
}

Is using a text/css link a good idea? I figured this is always called even if Javascript or Images are disabled?

This code basically makes the first site out of all my sites that gets opened by the user sets the Session ID, and then passes it on to the other sites.

Seems to work pretty well. You get a slight delay the very first time any of the sites opened and the ID is passed to the sites. But, you could do this via AJAX so the page loads fast. But, then you rely on Javascript being enabled.

Thoughts?

Matt H
  • 299
  • 3
  • 3
0

You really should look into SSO (single sign-on). One option for SSO is to use OpenID (as used on SO), and using it will make your life a lot easier.

Here's an article on it : http://devzone.zend.com/article/3581

wimvds
  • 12,790
  • 2
  • 41
  • 42
0

the cookies and their visibility is a problem. The browser accessing the new site would not send the session id of the old site to the server.

I think your read() does not use the ssid parameter you provide as session id but as the browser has no session with this domain the system generates one with new id as $id. Have a look if $_REQUEST['ssid'] exist in the database.

Custom session handler might a bit big for this job. You could just check if $_REQUEST['ssid'] exist in the session database and rewrite $_SESSION with it.

Antti Rytsölä
  • 1,485
  • 14
  • 24
  • sorry, i think the problem is not about the passing session id to new domain.. because it's still on testing phase i just use firefox addon to manually change the cookie value myself.. so there's no problem with the cookie passing! – PHP Newbie Jan 22 '11 at 03:02