Сеанси PHP у піддоменах


92

Я намагаюся встановити наступне:

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

Якщо користувач відвідує sub1.example.comабо sub2.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);

Ідентифікатори сеансу абсолютно однакові, але коли я викидаю $_SESSIONзмінну, вона не відображає обидва ключі, будь-який ключ, який я встановив для кожного домену.


Ви повинні також увімкнути це у своєму коді, див. Http://us2.php.net/manual/en/function.session-set-cookie-params.php
Residuum

1
У мене майже однакові установки (я встановив домен cookie сеансу із викликом "session_set_cookie_params"), і він працює нормально.
Мілен А. Радев

Ось приємна функція, яка працює stackoverflow.com/questions/2835486/…
boksiora

Відповіді:


134

Я не знаю, чи проблема все ще існує, але я просто зіткнувся з тією ж проблемою і вирішив її, встановивши назву сеансу перед викликом session_set_cookie_params():

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

Я нічого не змінив у своєму php.ini але зараз все працює нормально.


10
Я підтверджую, це вирішує проблему. Я втомився отримувати там свою відповідь: stackoverflow.com/questions/4948340/… . Але я знайшов його тут.
Роман

5
Працює ідеально! Шукав для цього вік. Це $some_name = session_name("some_name");зробило це. Дякую і підтримую.
Кіт,

4
Додавання session_name("domain");також бракувало інгредієнта для мене. Документація на php.net щодо цих налаштувань сеансу відсутня. На php.net є публікації спільноти, які вказують, що ім’я сесії потрібно визначити перед тим, як можна застосувати зміни до session_set_cookie_params ().
Девід Керролл,

3
так. підтверджено. приємний ходив там колами протягом століть;)
Даїті,

1
ПРИМІТКА ... довелося закрити браузер і перезапустити його, щоб він працював на сервері життя. Не залишайте жодної ini_set("session.cookie_domain", ".domain.com");причини, що спричиняла створення нового ідентифікатора сеансу при кожному оновленні.
Даїті,

24

Одна річ, яка може загадково запобігти читанню даних сеансу на піддомені, незважаючи на те, що файли cookie правильно встановлені, .example.com- це патч PHP Suhosin. Ви можете налаштувати все правильно, відповідно до прикладів у питанні, і це може просто не працювати.

Вимкніть такі налаштування сеансу Suhosin, і ви знову в справі:

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

5

Спробуйте використати:

session.cookie_domain = "example.com"

Замість:

session.cookie_domain = ".example.com"

Зверніть увагу на відсутність періоду на початку.

Будьте обережні, використовуючи це, оскільки воно підтримується не всіма браузерами.


9
Які браузери не підтримуються?
gawpertron

10
яка підтримка браузера тут? це серверна дія.
Куф,

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') для точно такого самого ефекту)


3

Я вирішив це так

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

Тому що я працював на localhost

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

не працював , він бачить .localhost як верхній рівень замість .com / .local / ... (я підозрюю)


Також виправлено для моєї машини - Ubuntu 14.04
dennis

3

Я підтвердив. жореон правильна. Я не можу коментувати, оскільки моєї репутації недостатньо, тому я публікую свій коментар тут.

Визначте константу у файлі конфігурації. Якщо ви хочете змінити його, не потрібно змінювати цілі файли.

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

Назва сеансу не може складатися лише з цифр, має бути принаймні одна буква. В іншому випадку кожен раз створюється новий ідентифікатор сеансу.

Використовуйте наступний код, щоб розпочати використання сеансу

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

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може бути різним для вашого випадку, але він повинен бути однаковим для кожного домену / субдомену. За замовчуванням це не завжди відповідає дійсності.


1

Використовуйте це, це працює:

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

це схоже на встановлення файлу cookie для tld ... або мені чогось не вистачає?
chacham15

1

Субдомен та кореневий домен Сеанси файлів 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); 
?>

0

Я розумію, що ви не хочете щось на зразок OpenID, як пропонує Джоел, але що ви хочете мати доступ до даних сеансу в кількох доменах.

Єдина можливість, яку я можу уявити як вирішення цієї проблеми, - це зберігати сесійні дані в базі даних і витягувати їх із цієї бази даних.


Правильно, хоча автентифікація є частиною того, що я хочу зробити, мене також цікавлять дані сеансу, які зберігаються під час роботи користувача.
dragonmantank

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


0

Я не можу говорити про інші версії PHP, але в 5.6.6, просто встановивши session.cookie_domainзначення вphp.ini файлі зробило трюк, щоб дозволити всім моїм субдоменам на iPage використовувати один і той же набір змінних сеансу.

Обов’язково видаліть із веб-переглядача всі наявні файли cookie, пов’язані з вашим доменом, для тестування.

session.cookie_domain = '.yourdomainname.example'

О, не знаю, чи має це якесь значення, але я також використовую автозапуск сеансу.

session.auto_start = 1

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

0

Я прочитав усі відповіді вище, я вважаю, що моя відповідь корисна для людей, які гуглить це:

  • переконайтеся, що браузери відправляють сеансові файли cookie назад на сервери (домену та субдоменів), встановіть домен сеансового файлу cookie як .example.com.

  • Переконайтесь, що PHP знайшов правильну "ціль" для відновлення змінної сеансу:

    • Якщо домен і субдомени вказують на одну машину (можливо, різні віртуальні хости), переконайтеся, що session_save_path що однаковий для всіх (я тестував)
    • Якщо домен та субдомени вказують на різні машини, спільне сховище (наприклад, база даних) найкраще підходить для збереження та відновлення даних сеансу (я ще не тестував). Використовуйте session_set_save_handlerдля цього.

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

}

?>


6
На яке питання ви відповідаєте? І як це покращує / покращує 9 інших відповідей?
random_user_name


-2

Швидке і брудне рішення полягає у використанні цього для вашого перенаправлення:

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

це додасть щось у рядку ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4до URL-адреси, що повідомляє PHP ідентифікатор сеансу, який він повинен використовувати.


3
Це також робить його вразливим до крадіжки сеансу :) Проблема полягає не в тому, що ідентифікатори сеансів не збігаються (вони є, див. Мій оновлений пост), а в тому, що дані не рухаються між доменами.
dragonmantank

Погоджено, це дуже вразливий ідентифікатор вихідної сесії у рядку запиту.
Ян Джеймісон

4
Файли cookie також надсилаються у вигляді простого тексту, це не відкриває жодних шляхів, які ще не були відкриті. Я не кажу, що це хороше рішення, але воно не менш безпечне, ніж використання файлів cookie.
sakabako 01.03.13

1
Це менш безпечно в тому сенсі, що користувачів можуть (обдурити) обмінюватися своєю URL-адресою і таким чином ділитися своїм активним ідентифікатором сеансу. Набагато менше шансів, що користувач мимоволі поділиться своїм cookie-файлом ідентифікатора сесії.
Bastiaan ten Klooster
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.