跨子域的PHP会话

我正在尝试设置以下内容:

auth.domain.com sub1.domain.com sub2.domain.com 

如果用户访问sub1.domain.com或sub2.domain.com并且他们没有login,他们将被推送到auth.domain.com并且可以login。sub1.domain.com和sub2.domain.com是两个单独的应用程序,但使用相同的凭据

我尝试在我的php.ini中设置以下内容:

 session.cookie_domain = ".domain.com" 

但它似乎并没有将信息从一个域传递给另一个域。

[编辑]

我尝试了以下内容:

sub1.domain.com/test.php

 session_set_cookie_params(0, '/', '.domain.com'); session_start(); print session_id() . "<br>"; $_SESSION['Regsitered'] = 1; echo '<a href="http://auth.domain.com/test.php">Change Sites</a>' 

auth.domain.com/test.php

 session_set_cookie_params(0, '/', '.domain.com'); session_start(); print session_id() . "<br>"; $_SESSION['Checked'] = 1; print_r($_SESSION); 

会话ID是完全相同的,但是当我转储$ _SESSIONvariables时,它不显示两个键,只要在每个域下设置的任何键。

[编辑2]

我更新了[编辑]

我不知道问题是否仍然存在,但我只是遇到了同样的问题,并解决了在调用session_set_cookie_params()之前设置会话名称:

 $some_name = session_name("some_name"); session_set_cookie_params(0, '/', '.some_domain.com'); session_start(); 

我没有改变我的php.ini,但现在一切工作正常。

有一件事可以神秘地阻止在子域上读取会话数据,尽pipecookies正确设置为.domain.com是PHP Suhosin补丁。 根据问题的例子,你可以正确地configuration所有的东西,它可以不工作。

将以下Suhosin会话设置closures,然后重新开始工作:

 suhosin.session.cryptua = Off suhosin.session.cryptdocroot = Off 

尝试使用:

 session.cookie_domain = "domain.com" 

代替:

 session.cookie_domain = ".domain.com" 

注意缺less的时期。

但是请小心使用,因为它不被所有浏览器支持。

我像这样解决了

 ini_set('session.cookie_domain', '.testdomain.dev'); session_start(); 

因为我在本地主机上工作

 ini_set('session.cookie_domain', '.localhost'); 

没有工作 ,它将.localhost视为顶级而不是.com / .local / …(我怀疑)

我也使用.dev,因为在OS X上工作似乎并没有解决.com作为HOSTS中的第一个

有这个确切的问题 – 我想在x.example.local上创build的会话值在example.local上可用,反之亦然。

我发现的所有解决scheme都是通过在.htaccess(或通过php.ini或ini_set)中使用php_value session.cookie_domain .example.local来更改会话域。

赶上是我设置所有子域session.cookie_domain (到目前为止确定),但也为主域。 在主域上设置session.cookie_domain显然是一个session.cookie_domain

基本上它为我工作的方式:

  • 为所有的SUBDOMAINS设置session.cookie_domain
  • 不要将其设置为主域

哦,是的,请确保该域名有一个顶级域名(就我而言.local)。 Http协议不允许cookies /会话存储在没有.tld的域上(即localhost不能工作,但是stuff.localhost会)。

编辑 :也请确保你总是清除你的浏览器cookies跨子域testing/debugging会话。 如果不这样做,浏览器将始终发送旧的会话cookie,该cookie可能没有设置正确的cookie_domain。 服务器将恢复旧的会话,因此你会得到错误的否定结果。 (在许多post中提到使用session_name('stuff')来获得完全相同的效果)

在每个域/子域上使用它:

 session_name('name'); ini_set('session.cookie_domain', '.example.com'); ini_set('session.save_path', '/var/lib/php/session'); session_start(); 

session.save_pathpath可能会因您的情况而不同,但在每个域/子域中应该相同 。 默认情况下并不总是这样。

我已确认。 乔伦的回答是正确的。 我不能评论,因为我的声誉是不够的,所以我在这里发表我的评论。

在configuration文件中定义常量。 如果你想改变它,不需要修改整个文件。

 define('ROOT_DOMAIN', 'mysite.com'); define('PHP_SESSION_NAME', 'MYSITE'); 

会话名称不能仅由数字组成,至less必须有一个字母。 否则,每次都会生成一个新的会话ID。

使用下面的代码开始使用会话

 session_name(PHP_SESSION_NAME); session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN); session_start(); 

我正在使用这个function:

 function load_session() { if (session_status() == PHP_SESSION_NONE) { session_name(PHP_SESSION_NAME); session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN); session_start(); } else { if (session_name() != PHP_SESSION_NAME) { session_destroy(); session_name(PHP_SESSION_NAME); session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN); session_start(); } } } load_session(); // put it in anywhere you want to use session 

使用这个,它的工作原理:

 ini_set('session.cookie_domain', substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100)); 

子域和根域Cookie会话组合使用

资源: http : //php.net//manual/tr/function.session-set-cookie-params.php

我testing了作品

 sub.exampledomain.com/sessionadd.php?id=123 exampledomain.com/sessionview.php // 123 

– 代码

 <?php $currentCookieParams = session_get_cookie_params(); $rootDomain = '.example.com'; session_set_cookie_params( $currentCookieParams["lifetime"], $currentCookieParams["path"], $rootDomain, $currentCookieParams["secure"], $currentCookieParams["httponly"] ); session_name('mysessionname'); session_start(); setcookie($cookieName, $cookieValue, time() + 3600, '/', $rootDomain); ?> 

我认为你不需要OpenID这样的东西,就像Joel所build议的那样,但是你希望跨多个域访问会话数据。

我认为解决这个问题的唯一可能性就是将会话数据存储在数据库中,并将其从数据库中提取出来。

我知道这是旧的,但这对我的多个域和子域在同一个框中正常工作。

 <?php define('site_domain','domain.com'); session_set_save_handler('_open', '_close', '_read', '_write', '_destroy', '_clean'); function _open(){ global $_sess_db; $db_user = 'user'; $db_pass = 'pass'; $db_host = 'localhost'; if ($_sess_db = mysql_connect($db_host, $db_user, $db_pass)){ return mysql_select_db('database', $_sess_db); } return false; } function _close(){ global $_sess_db; return mysql_close($_sess_db); } function _read($id){ global $_sess_db; $id = mysql_real_escape_string($id); $domain = mysql_real_escape_string(site_domain); $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT'])); $sql = "SELECT data FROM sessions WHERE id = '$id' AND domain = '$domain' AND agent = '$agent'"; if ($result = mysql_query($sql, $_sess_db)){ if (mysql_num_rows($result)){ $record = mysql_fetch_assoc($result); return $record['data']; } } return ''; } function _write($id, $data){ global $_sess_db; $access = time(); $id = mysql_real_escape_string($id); $access = mysql_real_escape_string($access); $data = mysql_real_escape_string($data); $domain = mysql_real_escape_string(site_domain); $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT'])); $sql = "REPLACE INTO sessions VALUES ('$id', '$access', '$data', '$domain', '$agent')"; return mysql_query($sql, $_sess_db); } function _destroy($id){ global $_sess_db; $id = mysql_real_escape_string($id); $domain = mysql_real_escape_string(site_domain); $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT'])); $sql = "DELETE FROM sessions WHERE id = '$id' AND domain = '$domain' AND agent = '$agent'"; return mysql_query($sql, $_sess_db); } function _clean($max){ global $_sess_db; $old = time() - $max; $old = mysql_real_escape_string($old); $domain = mysql_real_escape_string(site_domain); $agent = mysql_real_escape_string(isset($_SERVER['HTTP_USER_AGENT'])); $sql = "DELETE FROM sessions WHERE access < '$old' AND domain = '$domain' AND agent = '$agent'"; return mysql_query($sql, $_sess_db); } 

?>

我已阅读上述所有答案,我想我的答案是有用的人使用Google。

*确保浏览器将会话cookie发送回服务器(域和子域),将会话cookie域设置为“.example.com”。

*确保PHPfind正确的“目标”来恢复会话var – 如果域和子域指向同一台机器(也许不同的虚拟主机),请确保“session_save_path”对所有(我testing)是相同的 – 如果域和子域指向不同的机器,常见的存储(如数据库)是最好的保存和恢复会话数据(我还没有testing)。 使用“session_set_save_handler”来做到这一点。

只需在session_start()方法上面使用以下代码即可

 $sess_life_time = 21600; //in seconds $sess_path = "/"; $sess_domain = ".you-site-name.com"; $sess_secure = true; // if you have secured session $sess_httponly = true; // httponly flag session_set_cookie_params($sess_life_time, $sess_path, $sess_domain, $sess_secure, $sess_httponly); 

我也有类似的问题,但是这个解决scheme对我有好处,也许会在未来帮助别人

编辑php.ini

session.cookie_domain =“.example.com”

魔术就在这里

 suhosin.session.cryptdocroot = Off suhosin.cookie.cryptdocroot = Off 

https://www.sitepoint.com/community/t/sessions-across-subdomains-domain-com-phpsessid-changes/3013/19

我不能说其他版本的PHP,但在5.6.6中,只需在php.ini文件中设置session.cookie_domain值就可以让iPage上的所有子域共享同一组会话variables。

一定要从您的浏览器中删除与您的域相关的任何现有的cookie来testing。

 session.cookie_domain = '.yourdomainname.org' 

哦,不知道是否有什么区别,但我也使用会话自动启动。

 session.auto_start = 1 

一个快速和肮脏的解决scheme是使用这个redirect:

 header( $url.'?'.session_name().'='.session_id() ); 

这会在?PHPSESSID = etnm7kbuf5lg0r6tv7je6ehtn4中添加一些内容给URL,告诉PHP它应该使用的会话ID。