94

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

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

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

sub1.example.com并且sub2.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变量时,它不会显示两个键,只是我在每个域下设置的任何键。

4

17 回答 17

139

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

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

我没有改变任何东西,php.ini但现在一切正常。

于 2009-09-22T00:35:37.877 回答
24

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

关闭以下 Suhosin 会话设置,您就可以重新开始工作了:

suhosin.session.cryptua = Off 
suhosin.session.cryptdocroot = Off
于 2011-06-25T12:49:12.783 回答
5

尝试使用:

session.cookie_domain = "example.com"

代替:

session.cookie_domain = ".example.com"

请注意开头缺少的期间。

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

于 2009-06-30T15:17:16.420 回答
4

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

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

问题是我设置了session.cookie_domain所有子域(到目前为止还可以),但也设置了主域。在主域上设置session.cookie_domain显然是禁忌。

基本上它对我有用的方式:

  • session.cookie_domain为所有子域设置。
  • 不要为主域设置它

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

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

于 2013-12-03T14:10:00.780 回答
3

我这样解决了

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

因为我在本地工作

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

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

于 2012-04-12T17:27:13.100 回答
3

我已经确认了。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
于 2015-05-12T17:56:34.157 回答
2

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

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

对于您的情况,路径可能会有所不同,但在每个域/子域上session.save_path应该是相同的。默认情况下并非总是如此。

于 2013-11-17T07:03:45.050 回答
1

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

ini_set('session.cookie_domain', 
    substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
于 2010-10-05T20:22:21.163 回答
1

子域和根域 Cookie Sessions 组合使用

资源: 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); 
?>
于 2014-08-28T16:26:39.237 回答
0

我知道这很旧,但这对我来说在同一个盒子上有多个域和子域时效果很好。

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

}

?>

于 2012-01-17T16:46:08.277 回答
0

我已经阅读了上面的所有答案,我认为我的答案对谷歌搜索的人有帮助:

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

  • 确保 PHP 找到正确的“目标”来恢复会话变量:

    • 如果域和子域指向同一台机器(可能是不同的虚拟主机),请确保session_save_path所有域都相同(我测试过)
    • 如果域和子域指向不同的机器,公共存储(如数据库)最适合保存和恢复会话数据(我还没有测试过)。用来session_set_save_handler做那个。
于 2012-12-21T03:55:28.413 回答
0

我的想法是,您不想要像 Joel 建议的 OpenID 之类的东西,但您希望能够访问多个域的会话数据。

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

于 2009-06-30T15:18:51.953 回答
0

只需尝试使用上述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);
于 2014-07-09T10:50:18.140 回答
0

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

请务必从浏览器中删除与您的域相关的任何现有 cookie 以进行测试。

session.cookie_domain = '.yourdomainname.example'

哦,不知道它是否有任何区别,但我也在使用会话自动启动。

session.auto_start = 1
于 2016-11-03T17:13:52.477 回答
0

利用 :

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);
于 2020-04-13T20:32:16.483 回答
0

我有类似的问题,但是,这个解决方案对我有好处,也许将来会帮助其他人

编辑 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

于 2016-07-26T19:06:54.703 回答
-2

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

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

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

于 2009-06-30T18:58:54.090 回答