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

auth.example.com
sub1.example.com
sub2.example.com


如果用户访问sub1.example.comsub2.example.com并且他们未登录,他们将被重定向到auth.example.com并可以登录。

sub1.example.comsub2.example.com是两个单独的应用程序,但是使用相同的凭据。

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

session.cookie_domain = ".example.com"


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

[编辑]

我尝试了以下操作:

sub1.example.com/test.php

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


auth.example.com/test.php

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


会话ID正是相同,但是当我转出$_SESSION变量时,它不会同时显示两个键,而不会显示我在每个域下设置的任何键。

评论

您还必须在代码中启用它,请参见http://us2.php.net/manual/en/function.session-set-cookie-params.php

我的设置几乎相同(我通过调用“ session_set_cookie_params”来设置会话cookie域),并且工作正常。

这是一个很好的功能,可以正常工作stackoverflow.com/questions/2835486/…

#1 楼

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

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


我什么都没改变在我的php.ini中,但现在一切正常。

评论


我确认,它可以解决问题。我累了要在那里得到我的答案:stackoverflow.com/questions/4948340/…。但是我在这里找到的。

–罗马
2011-02-10 17:04

完美的作品!一直在寻找这个年龄。那是$ some_name = session_name(“ some_name”);做到了。谢谢你并支持。

–套件
2011年3月17日在12:19

添加session_name(“ domain”);也是我所缺少的成分。缺少有关这些会话设置的php.net文档。 php.net上有一些社区帖子,指出必须先定义session.name,然后才能应用对session_set_cookie_params()的更改。

–大卫·卡罗尔(David Carroll)
2011年7月3日在7:28

是的确认。一个不错的人在那里转悠了好久;)

–Daithí
2012年1月15日20:46

注意...必须关闭我的浏览器并重新启动才能使其在生命服务器上正常工作。忽略任何ini_set(“ session.cookie_domain”,“ .domain.com”);因为这导致它每次刷新都创建新的会话ID。

–Daithí
2012年1月15日21:30

#2 楼

尽管Cookie已正确设置为.example.com,但可以神秘地阻止会话数据在子域上读取的一件事是PHP Suhosin补丁。按照问题中的示例,您可以正确配置所有内容,并且无法正常使用。

关闭以下Suhosin会话设置,即可恢复正常工作:

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


#3 楼

尝试使用:

session.cookie_domain = "example.com"


而不是:

session.cookie_domain = ".example.com"


请注意开头缺少的时间段。

但是请小心使用,因为并非所有浏览器都支持它。

评论


不支持哪些浏览器?

– gawpertron
2011-2-16在19:09

这里对浏览器的支持是什么?这是服务器端的操作。

–库夫
14-10-20在17:45

#4 楼

遇到了这个确切的问题-我希望在x.example.local上创建的会话值可以在example.local上使用,反之亦然。

我发现的所有解决方案都说要通过使用 .htaccess中的php_value session.cookie_domain .example.local(或通过php.ini或ini_set)。

问题是我为所有子域(到目前为止还可以)以及主域设置了session.cookie_domain。在主域上设置session.cookie_domain显然是不行的。

基本上对我有用:


为所有子域设置session.cookie_domain

不要为主要DOMAIN设置它

哦,是的,请确保该域具有TLD(在我的情况下是.local)。 Http协议不允许将cookie /会话存储在没有.tld的域中(即localhost无法正常工作,但stuff.localhost可以正常工作)。

编辑:还要确保您始终清除自己的测试/调试跨子域的会话时的浏览器Cookie。如果您不这样做,您的浏览器将始终发送旧的会话cookie,该会话cookie可能尚未设置正确的cookie_domain。服务器将恢复旧的会话,因此您将得到错误的负面结果。 (在很多帖子中都提到使用session_name('stuff')可以达到完全相同的效果)

#5 楼

我这样解决了

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


因为我在本地主机上工作

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


不起作用,它会将.localhost视为顶层,而不是.com / .local / ...(我怀疑)

评论


还为我的机器修复了它-Ubuntu 14.04

–丹尼斯
2015年2月1日于10:41

#6 楼

我已经确认了joreon的答案是正确的。我不能发表评论,因为我的声誉还不够,所以我在这里发表评论。

在配置文件中定义常量。如果要更改它,则无需修改整个文件。

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


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

使用以下代码开始使用会话

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


我正在使用此功能:

function load_session() {
    if (session_status() == PHP_SESSION_NONE) {
        session_name(PHP_SESSION_NAME);
        session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
        session_start();
    } elseif (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


#7 楼

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

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


session.save_path的路径因您的情况而异,但在每个域/子域上都应该相同。默认情况下并不总是如此。

#8 楼

使用它,它可以工作:

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


评论


这看起来像是为tld设置cookie ...还是我错过了一些东西?

–chacham15
15年1月20日在23:58

#9 楼

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

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

我已经测试过作品

sub.example.com/sessionadd.php?id=123

example.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); 
?>


#10 楼

我的想法是,您不希望像Joel所建议的那样使用OpenID之类的东西,但是您想跨多个域访问会话数据。

我能想到的唯一可能性解决该问题的方法是将会话数据存储在数据库中,然后将其从该数据库中拉出。

评论


正确,虽然身份验证是我要做的一部分,但我也对在用户工作时存储的会话数据感兴趣。

– Dragonmantank
09年6月30日在18:47

#11 楼

我遇到了类似的问题,但是,该解决方案对我很有用,也许将来会对其他人有所帮助

编辑php.ini


session.cookie_domain =“ .example.com”


魔术就在这里

suhosin.session.cryptdocroot = Off

suhosin.cookie.cryptdocroot = Off


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

#12 楼

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

请确保从浏览器中删除所有与您的域相关的现有Cookie进行测试。

session.cookie_domain = '.yourdomainname.example'


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

session.auto_start = 1


#13 楼

只需尝试在session_start()方法上方使用下面的代码

$sess_life_time = 21600; //in seconds
$sess_path = "/";
$sess_domain = ".example.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);


#14 楼

我已经阅读了上面所有的答案,我认为我的答案对使用以下工具的人很有帮助:


确保浏览器将会话Cookie发送回服务器(域和子域),设置会话cookie域,如.example.com

确保PHP找到正确的“目标”来还原会话变量:


如果域和子域指向同一台计算机(也许是不同的虚拟主机),请确保session_save_path对于所有主机(我已测试)都相同。
如果域和子域指向不同的计算机,则公共存储(如数据库)最适合保存和还原会话数据(我没有还没有测试)。使用session_set_save_handler来执行此操作。




#15 楼

我知道这很旧了,但是对我来说,在同一个盒子上同时使用多个域和子域就可以了。

<?php
define('site_domain','example.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);

}


?>

评论


您在回答什么问题?以及如何改善/增强其他9个答案?

–random_user_name
2012年10月28日在21:20

#16 楼

使用:

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);


#17 楼

一种快速而又肮脏的解决方案是将其用于重定向:

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


这会将类似?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4的内容添加到URL,从而告诉PHP会话ID应该使用。

评论


这也使它很容易遭受会话盗窃:)问题不是会话ID不匹配(它们是,请参阅我更新的帖子),而是数据在域之间不移动。

– Dragonmantank
09年6月30日在19:08

同意,这很容易受到攻击,将会话ID保留在查询字符串中。

–伊恩·贾米森(Ian Jamieson)
13年2月18日在10:02

Cookies也以纯文本形式发送,这不会打开任何尚未打开的途径。我并不是说这是一个很好的解决方案,但它的安全性不亚于使用cookie。

–sakabako
13年1月1日在19:48

从用户可能(被诱使)共享其URL并因此共享其活动会话ID的意义上说,这种方法不太安全。用户不经意间共享其会话ID cookie的可能性要小得多。

–巴伐利亚十个克劳斯特
17-10-9在9:33