跨子域的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_path
path可能会因您的情况而不同,但在每个域/子域中应该相同 。 默认情况下并不总是这样。
我已确认。 乔伦的回答是正确的。 我不能评论,因为我的声誉是不够的,所以我在这里发表我的评论。
在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
我不能说其他版本的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。