跨子域的 PHP 会话
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1064243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
PHP Sessions across sub domains
提问by dragonmantank
I am trying to set up the following:
我正在尝试设置以下内容:
auth.example.com
sub1.example.com
sub2.example.com
If the user visits sub1.example.comor sub2.example.comand they are not logged in, they get redirected over to auth.example.comand can log in.
如果用户访问sub1.example.com或sub2.example.com未登录,他们将被重定向到auth.example.com并可以登录。
sub1.example.comand sub2.example.comare two separate applications but use the same credentials.
sub1.example.com并且sub2.example.com是两个独立的应用程序,但使用相同的凭据。
I tried setting the following in my php.ini:
我尝试在我的 php.ini 中设置以下内容:
session.cookie_domain = ".example.com"
but it doesn't seem to be passing the information from one domain to the other.
但它似乎并没有将信息从一个域传递到另一个域。
[Edit]
[编辑]
I tried the following:
我尝试了以下方法:
sub1.example.com/test.php
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
auth.example.com/test.php
session_set_cookie_params(0, '/', '.example.com');
session_start();
print session_id() . "<br>";
$_SESSION['Checked'] = 1;
print_r($_SESSION);
The session IDs are exactly the same but when I dump out the $_SESSIONvariable it doesn't show both keys, just whatever key I set under each domain.
会话 ID 完全相同,但是当我转储$_SESSION变量时,它不会显示两个键,而是我在每个域下设置的任何键。
回答by jeroen
I do not know if the problem still exists, but I just ran into the same problem and solved it setting a session name before calling session_set_cookie_params():
我不知道问题是否仍然存在,但我遇到了同样的问题并解决了它在调用之前设置会话名称session_set_cookie_params():
$some_name = session_name("some_name");
session_set_cookie_params(0, '/', '.example.com');
session_start();
I have changed nothing in my php.inibut now everything is working fine.
我没有改变任何东西,php.ini但现在一切正常。
回答by drewm
One thing which can mysteriously prevent session data being read on a subdomain, despite cookies being correctly set to .example.comis the PHP Suhosin patch. You can have everything configured correctly, as per the examples in the question, and it can just not work.
尽管 cookie 设置正确,但可以神秘地阻止在子域上读取会话数据的一件事.example.com是 PHP Suhosin 补丁。根据问题中的示例,您可以正确配置所有内容,但它无法正常工作。
Turn the following Suhosin session settings off, and you're back in business:
关闭以下 Suhosin 会话设置,您就可以重新开始工作:
suhosin.session.cryptua = Off
suhosin.session.cryptdocroot = Off
回答by George Claghorn
Try using:
尝试使用:
session.cookie_domain = "example.com"
Instead of:
代替:
session.cookie_domain = ".example.com"
Note the missing period at beginning.
请注意开头缺少的句点。
Be careful using this, though, because it is not supported by all browsers.
但是请小心使用它,因为并非所有浏览器都支持它。
回答by Valentin Florea
Had this exact problem - I wanted session values created on x.example.local to be available on example.local and vice-versa.
有这个确切的问题 - 我希望在 x.example.local 上创建的会话值在 example.local 上可用,反之亦然。
All solutions I found said to change the Session domain by using
php_value session.cookie_domain .example.localin .htaccess (or via php.ini or via ini_set).
我发现的所有解决方案都说通过php_value session.cookie_domain .example.local在 .htaccess 中使用(或通过 php.ini 或通过 ini_set)来更改会话域
。
The catch was I was setting the session.cookie_domainfor all subdomains (so far ok) but also for the main domain. Setting the session.cookie_domainon the main domain is apparently a no-no.
问题是我正在session.cookie_domain为所有子域(到目前为止还可以)以及主域设置 。session.cookie_domain在主域上设置显然是禁忌。
Basically the way it worked for me:
基本上它对我有用的方式:
- set the
session.cookie_domainfor ALL SUBDOMAINS. - don't set it for the main DOMAIN
session.cookie_domain为所有子域设置。- 不要为主域设置它
Oh yes, please make sure the domain has a TLD (in my case .local). Http protocol doesn't allow cookies/sessions to be stored on a domain without .tld (ie localhost won't work, but stuff.localhost will).
哦,是的,请确保该域具有 TLD(在我的情况下为 .local)。Http 协议不允许将 cookie/session 存储在没有 .tld 的域中(即 localhost 不起作用,但 stuff.localhost 可以)。
EDIT: Also make sure you always clear your browser cookies while testing/debugging sessions across subdomains. If you don't, your browser will always send the old session cookie which probably doesn't have the correct cookie_domain set yet. The server will revive the old session and therefore you'll get false negative results. (in many posts it's mentioned to use session_name('stuff') for the exact same effect)
编辑:还要确保在跨子域测试/调试会话时始终清除浏览器 cookie。如果不这样做,您的浏览器将始终发送旧的会话 cookie,该 cookie 可能尚未设置正确的 cookie_domain。服务器将恢复旧会话,因此您将得到假阴性结果。(在许多帖子中提到使用 session_name('stuff') 来达到完全相同的效果)
回答by xtds
I solved it like this
我是这样解决的
ini_set('session.cookie_domain', '.testdomain.example');
session_start();
Because I was working on localhost
因为我在本地主机上工作
ini_set('session.cookie_domain', '.localhost');
wasn't working, it sees .localhost as the toplevel instead of .com/.local/... (I suspect)
没有工作,它认为 .localhost 作为顶层而不是 .com/.local/...(我怀疑)
回答by Terry Lin
I have confirmed. joreon's answer is correct. I cannot comment because my reputation is not enough so I post my comment here.
我已经确认了。joreon的回答是正确的。我无法发表评论,因为我的声誉不够,所以我在这里发表评论。
Define the constant in a config file. If you want to change it, no need to modify whole files.
在配置文件中定义常量。如果要更改它,无需修改整个文件。
define('ROOT_DOMAIN', 'mysite.example');
define('PHP_SESSION_NAME', 'MYSITE');
The session name can't consist of digits only, at least one letter must be present. Otherwise, a new session id is generated every time.
会话名称不能仅由数字组成,必须至少包含一个字母。否则,每次都会生成一个新的会话 ID。
Use the following code to start using session
使用以下代码开始使用会话
session_name(PHP_SESSION_NAME);
session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
session_start();
I'm using this function:
我正在使用这个功能:
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
回答by Andrii Nemchenko
Use it on every domain/subdomain:
在每个域/子域上使用它:
session_name('name');
ini_set('session.cookie_domain', '.example.com');
ini_set('session.save_path', '/var/lib/php/session');
session_start();
Path for session.save_pathcan be different for your case but it should be the sameon every domain/subdomain. It is not always true by default.
session.save_path对于您的情况,路径可能不同,但在每个域/子域上都应该相同。默认情况下并不总是如此。
回答by Limitless isa
Sub domain and root domain Cookie Sessions Combined Use
子域和根域 Cookie Sessions 结合使用
Resource: http://php.net//manual/tr/function.session-set-cookie-params.php
资源:http: //php.net//manual/tr/function.session-set-cookie-params.php
I've tested works
我已经测试过了
sub.example.com/sessionadd.php?id=123
example.com/sessionview.php // 123
-- Codes
-- 代码
<?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);
?>
回答by Ivan
Use this , it works:
使用这个,它的工作原理:
ini_set('session.cookie_domain',
substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
回答by Ian
I know this is old but this works fine for me with multiple domains and sub domains on the same box.
我知道这很旧,但这对我来说很好,在同一个盒子上有多个域和子域。
<?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);
}
?>
?>

