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
ฉันมีการตั้งค่าเกือบเหมือนกัน (ฉันตั้งค่าโดเมนคุกกี้เซสชันด้วยการเรียกไปที่ "session_set_cookie_params") และทำงานได้ดี
Milen A.Radev

นี่คือฟังก์ชั่นที่ดีที่ใช้งานได้ 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");ที่ทำมัน ขอบคุณและโหวตให้คะแนน
Kit

4
การเพิ่มsession_name("domain");เป็นส่วนผสมที่ขาดหายไปสำหรับฉันเช่นกัน ไม่มีเอกสารประกอบใน php.net เกี่ยวกับการตั้งค่าเซสชันเหล่านี้ มีโพสต์ของชุมชนบน php.net ที่ระบุว่าจำเป็นต้องกำหนด session.name ก่อนที่จะสามารถใช้การเปลี่ยนแปลง session_set_cookie_params () ได้
David Carroll

3
ใช่ ได้รับการยืนยัน คนดีกำลังวนเวียนอยู่ในแวดวงมานานแล้ว;)
Daithí

1
หมายเหตุ ... ต้องปิดเบราว์เซอร์ของฉันและรีสตาร์ทเพื่อให้มันทำงานบนเซิร์ฟเวอร์ชีวิต ละเว้นini_set("session.cookie_domain", ".domain.com");สาเหตุใด ๆ ที่ทำให้เกิดการสร้างรหัสเซสชันใหม่ทุกครั้งที่รีเฟรช
Daithí

24

สิ่งหนึ่งที่สามารถป้องกันการอ่านข้อมูลเซสชันบนโดเมนย่อยได้อย่างลึกลับแม้ว่าจะตั้งค่าคุกกี้อย่างถูกต้อง.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
มีการสนับสนุนเบราว์เซอร์อะไรบ้างที่นี่? นี่คือการดำเนินการฝั่งเซิร์ฟเวอร์
Kuf

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สำหรับ SUBDOMAINS ทั้งหมด
  • อย่าตั้งค่าสำหรับ DOMAIN หลัก

โอ้ใช่โปรดตรวจสอบให้แน่ใจว่าโดเมนมี TLD (ในกรณีของฉันคือ. local) โปรโตคอล Http ไม่อนุญาตให้เก็บคุกกี้ / เซสชันบนโดเมนที่ไม่มี. tld (เช่น localhost จะไม่ทำงาน แต่ stuff.localhost จะ)

แก้ไข : ตรวจสอบให้แน่ใจว่าคุณล้างคุกกี้ของเบราว์เซอร์อยู่เสมอในขณะที่ทดสอบ / แก้ไขข้อบกพร่องในโดเมนย่อย หากคุณไม่ทำเช่นนั้นเบราว์เซอร์ของคุณจะส่งคุกกี้เซสชันเก่าเสมอซึ่งอาจยังไม่ได้ตั้งค่า cookie_domain ที่ถูกต้อง เซิร์ฟเวอร์จะฟื้นฟูเซสชันเก่าดังนั้นคุณจะได้รับผลลัพธ์เชิงลบที่ผิดพลาด (ในหลาย ๆ โพสต์มีการกล่าวถึงการใช้ session_name ('stuff') เพื่อให้ได้ผลเช่นเดียวกัน)


3

ก็แก้เป็นแบบนี้

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

เพราะฉันทำงานกับ localhost

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

ใช้งานไม่ได้มันเห็น. localhost เป็น toplevel แทนที่จะเป็น. com / .local / ... (ฉันสงสัย)


แก้ไขให้เครื่องของฉันด้วย - Ubuntu 14.04
dennis

3

ฉันยืนยันแล้ว คำตอบของjoreonถูกต้อง ฉันไม่สามารถแสดงความคิดเห็นได้เนื่องจากชื่อเสียงของฉันไม่เพียงพอดังนั้นฉันจึงโพสต์ความคิดเห็นไว้ที่นี่

กำหนดค่าคงที่ในไฟล์กำหนดค่า หากคุณต้องการเปลี่ยนแปลงไม่จำเป็นต้องแก้ไขทั้งไฟล์

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

ดูเหมือนว่ามันตั้งค่าคุกกี้สำหรับ tld ... หรือฉันพลาดอะไรไป?
chacham15

1

โดเมนย่อยและโดเมนรากเซสชันคุกกี้รวมการใช้งาน

แหล่งข้อมูล: 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 เช่นที่ Joel แนะนำ แต่คุณต้องการเข้าถึงข้อมูลเซสชันในหลายโดเมน

ความเป็นไปได้เดียวที่ฉันสามารถคิดว่าเป็นวิธีแก้ปัญหานั้นคือการจัดเก็บ sessiondata ในฐานข้อมูลและดึงออกจากฐานข้อมูลนั้น


ถูกต้องในขณะที่การพิสูจน์ตัวตนเป็นส่วนหนึ่งของสิ่งที่ฉันต้องการทำ แต่ฉันก็สนใจข้อมูลเซสชันที่เก็บไว้ในขณะที่ผู้ใช้ทำงาน
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 แชร์ชุดตัวแปรเซสชันเดียวกัน

อย่าลืมลบคุกกี้ที่มีอยู่ที่เกี่ยวข้องกับโดเมนของคุณออกจากเบราว์เซอร์เพื่อทดสอบ

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

ฉันได้อ่านคำตอบทั้งหมดข้างต้นแล้วฉันคิดว่าคำตอบของฉันมีประโยชน์สำหรับผู้ที่ใช้ Googling สิ่งนี้:

  • ให้แน่ใจว่าเบราว์เซอร์ส่งเซสชั่นคุกกี้กลับไปยังเซิร์ฟเวอร์ (โดเมนและโดเมนย่อย) .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=etnm7kbuf5lg0r6tv7je6ehtn4URL ซึ่งจะบอก PHP ถึงรหัสเซสชันที่ควรใช้


3
นอกจากนี้ยังทำให้เสี่ยงต่อการถูกขโมยเซสชันอีกด้วย :) ปัญหาไม่ได้อยู่ที่รหัสเซสชันไม่ตรงกัน (ดูโพสต์ที่อัปเดตของฉัน) แต่ข้อมูลไม่ได้ย้ายไปมาระหว่างโดเมน
dragonmantank

เห็นด้วยนี่เป็นความเสี่ยงอย่างมากที่จะทิ้งรหัสเซสชันไว้ในสตริงข้อความค้นหา
Ian Jamieson

4
นอกจากนี้คุกกี้ยังถูกส่งเป็นข้อความธรรมดาซึ่งไม่ได้เปิดช่องทางใด ๆ ที่ยังไม่ได้เปิดอยู่ ฉันไม่ได้บอกว่ามันเป็นทางออกที่ดี แต่ก็ปลอดภัยไม่น้อยไปกว่าการใช้คุกกี้
sakabako

1
มีความปลอดภัยน้อยกว่าในแง่ที่ผู้ใช้อาจ (ถูกหลอกให้) แชร์ URL และแชร์ ID เซสชันที่ใช้งานอยู่ มีโอกาสน้อยกว่ามากที่ผู้ใช้จะแชร์คุกกี้รหัสเซสชันโดยไม่เจตนา
Bastiaan ten Klooster
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.