Sesi PHP di seluruh sub domain

92

Saya mencoba menyiapkan berikut ini:

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

Jika pengguna mengunjungi sub1.example.comatau sub2.example.comdan mereka tidak masuk, mereka dialihkan ke auth.example.comdan dapat masuk.

sub1.example.comdan sub2.example.commerupakan dua aplikasi terpisah tetapi menggunakan kredensial yang sama.

Saya mencoba mengatur yang berikut ini di php.ini saya:

session.cookie_domain = ".example.com"

tetapi tampaknya tidak meneruskan informasi dari satu domain ke domain lainnya.

[Sunting]

Saya mencoba yang berikut ini:

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 sesi persis sama tetapi ketika saya membuang $_SESSIONvariabel itu tidak menampilkan kedua kunci, hanya kunci apa pun yang saya tetapkan di bawah setiap domain.

dragonmantank
sumber
Anda harus mengaktifkannya juga di kode Anda, lihat http://us2.php.net/manual/en/function.session-set-cookie-params.php
Residuum
1
Saya memiliki penyiapan yang hampir sama (saya menyetel domain cookie sesi dengan panggilan ke "session_set_cookie_params") dan berfungsi dengan baik.
Milen A. Radev
Ini adalah fungsi bagus yang berfungsi stackoverflow.com/questions/2835486/…
boksiora

Jawaban:

134

Saya tidak tahu apakah masalahnya masih ada, tetapi saya baru saja mengalami masalah yang sama dan menyelesaikannya dengan menetapkan nama sesi sebelum memanggil session_set_cookie_params():

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

Saya tidak mengubah apa pun dalam diri saya php.initetapi sekarang semuanya bekerja dengan baik.

jeroen
sumber
10
Saya mengonfirmasi, itu menyelesaikan masalah. Saya lelah mendapatkan jawaban saya di sana: stackoverflow.com/questions/4948340/… . Tapi saya menemukannya di sini.
Roman
5
Bekerja dengan sempurna! Sudah lama mencari ini. Itu $some_name = session_name("some_name");yang melakukannya. Terima kasih dan upvote.
Kit
4
Menambahkan session_name("domain");adalah bahan yang hilang bagi saya juga. Dokumentasi di php.net tentang pengaturan sesi ini kurang. Ada postingan komunitas di php.net yang menunjukkan session.name perlu didefinisikan sebelum perubahan session_set_cookie_params () bisa diterapkan.
David Carroll
3
ya. dikonfirmasi. yang bagus berkeliling-keliling selama berabad-abad di sana;)
Daithí
1
CATATAN ... harus menutup browser saya dan memulai ulang agar dapat berfungsi di server kehidupan. Tinggalkan ini_set("session.cookie_domain", ".domain.com");penyebab apa pun yang menyebabkannya membuat id sesi baru dengan setiap penyegaran.
Daithí
24

Satu hal yang secara misterius dapat mencegah data sesi dibaca di subdomain, meskipun cookie disetel dengan benar .example.comadalah patch Suhosin PHP. Anda dapat mengatur semuanya dengan benar, sesuai contoh dalam pertanyaan, dan itu tidak bisa berfungsi.

Nonaktifkan pengaturan sesi Suhosin berikut, dan Anda kembali berbisnis:

suhosin.session.cryptua = Off 
suhosin.session.cryptdocroot = Off
drewm
sumber
5

Coba gunakan:

session.cookie_domain = "example.com"

Dari pada:

session.cookie_domain = ".example.com"

Perhatikan periode yang hilang di awal.

Berhati-hatilah saat menggunakannya, karena tidak didukung oleh semua browser.

George Claghorn
sumber
9
Browser mana yang tidak didukung?
gawpertron
10
Dukungan browser apa yang dibutuhkan di sini? ini adalah tindakan sisi server.
Kuf
4

Punya masalah persis seperti ini - Saya ingin nilai sesi yang dibuat di x.example.local tersedia di example.local dan sebaliknya.

Semua solusi yang saya temukan mengatakan untuk mengubah domain Sesi dengan menggunakan php_value session.cookie_domain .example.localdi .htaccess (atau melalui php.ini atau melalui ini_set).

Hasil tangkapannya adalah saya mengatur session.cookie_domainuntuk semua subdomain (sejauh ini ok) tetapi juga untuk domain utama. Pengaturan session.cookie_domaindomain utama tampaknya tidak-tidak.

Pada dasarnya cara itu berhasil bagi saya:

  • setel session.cookie_domainuntuk SEMUA SUBDOMAIN.
  • jangan setel untuk DOMAIN utama

Oh ya, pastikan domain tersebut memiliki TLD (dalam kasus saya .local). Protokol Http tidak mengizinkan cookie / sesi disimpan di domain tanpa .tld (yaitu localhost tidak akan berfungsi, tetapi stuff.localhost akan).

EDIT : Pastikan juga Anda selalu menghapus cookie browser saat menguji / debugging sesi di seluruh subdomain. Jika tidak, browser Anda akan selalu mengirimkan cookie sesi lama yang mungkin belum memiliki cookie_domain yang benar. Server akan menghidupkan kembali sesi lama dan oleh karena itu Anda akan mendapatkan hasil negatif palsu. (di banyak posting disebutkan menggunakan session_name ('stuff') untuk efek yang sama persis)

Valentin Florea
sumber
3

Saya menyelesaikannya seperti ini

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

Karena saya bekerja di localhost

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

tidak berfungsi , ia melihat .localhost sebagai level teratas, bukan .com / .local / ... (Saya curiga)

xtds
sumber
Juga memperbaikinya untuk mesin saya - Ubuntu 14.04
dennis
3

Saya sudah konfirmasi. joreonjawaban benar. Saya tidak bisa berkomentar karena reputasi saya tidak cukup jadi saya posting komentar saya di sini.

Tentukan konstanta dalam file konfigurasi. Jika Anda ingin mengubahnya, tidak perlu mengubah seluruh file.

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

Nama sesi tidak boleh hanya terdiri dari angka, setidaknya harus ada satu huruf. Jika tidak, ID sesi baru dibuat setiap saat.

Gunakan kode berikut untuk mulai menggunakan sesi

session_name(PHP_SESSION_NAME);
session_set_cookie_params(0, '/', '.' . ROOT_DOMAIN);
session_start();

Saya menggunakan fungsi ini:

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
Terry Lin
sumber
2

Gunakan di setiap domain / subdomain:

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

Path untuk session.save_pathdapat berbeda untuk kasus Anda tetapi harus sama di setiap domain / subdomain. Ini tidak selalu benar secara default.

Andrii Nemchenko
sumber
1

Gunakan ini, ini berhasil:

ini_set('session.cookie_domain', 
    substr($_SERVER['SERVER_NAME'],strpos($_SERVER['SERVER_NAME'],"."),100));
Ivan
sumber
Sepertinya ini menyetel cookie untuk tld ... atau apakah saya melewatkan sesuatu?
chacham15
1

Penggunaan Gabungan Sesi Cookie sub domain dan domain root

Sumber daya: http://php.net//manual/tr/function.session-set-cookie-params.php

Saya telah menguji karya

sub.example.com/sessionadd.php?id=123

example.com/sessionview.php // 123

- Kode

<?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); 
?>
Isa tak terbatas
sumber
0

Saya mendapatkan ide bahwa Anda tidak menginginkan sesuatu seperti OpenID, seperti yang disarankan Joel, tetapi Anda ingin memiliki akses ke data sesi di beberapa domain.

Satu-satunya kemungkinan yang dapat saya anggap sebagai solusi untuk masalah itu adalah menyimpan data sesi dalam database, dan menariknya keluar dari database itu.

Thomas
sumber
Benar, sementara otentikasi adalah bagian dari apa yang ingin saya lakukan, saya juga tertarik dengan data sesi yang disimpan saat pengguna bekerja.
dragonmantank
0

Saya tidak dapat berbicara untuk versi lain dari PHP, tetapi di 5.6.6, cukup mengatur session.cookie_domainnilai dalam php.inifile telah melakukan trik untuk memungkinkan semua subdomain saya di iPage berbagi kumpulan variabel sesi yang sama.

Pastikan untuk menghapus cookie yang ada terkait dengan domain Anda dari browser Anda untuk diuji.

session.cookie_domain = '.yourdomainname.example'

Oh, tidak tahu apakah ada bedanya tapi saya juga menggunakan sesi mulai otomatis.

session.auto_start = 1
pengguna3232196
sumber
0

Cukup coba gunakan kode berikut tepat di atas session_start()metode

$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);
mohsin.mr
sumber
0

Saya telah membaca semua jawaban di atas, saya rasa jawaban saya sangat membantu orang googling ini:

  • pastikan browser mengirim cookie sesi kembali ke server (dari domain dan sub-domain), setel domain cookie sesi sebagai .example.com.

  • Pastikan PHP menemukan "target" yang tepat untuk memulihkan variabel sesi:

    • Jika domain dan subdomain mengarah ke mesin yang sama (mungkin host virtual yang berbeda), pastikan session_save_pathsama untuk semua (saya uji)
    • Jika domain dan subdomain mengarah ke mesin yang berbeda, penyimpanan umum (seperti database) paling baik untuk menyimpan dan memulihkan data sesi (saya belum menguji). Gunakan session_set_save_handleruntuk melakukan itu.
pengguna953985
sumber
0

Saya tahu ini sudah tua tetapi ini berfungsi dengan baik untuk saya dengan beberapa domain dan sub domain di kotak yang sama.

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

}

?>

Ian
sumber
6
Pertanyaan apa yang Anda jawab? Dan bagaimana hal ini meningkatkan / menyempurnakan 9 jawaban lainnya?
random_user_name
0

Penggunaan:

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);
Shakil Ahmmed
sumber
-2

Solusi cepat dan kotor adalah menggunakan ini untuk pengalihan Anda:

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

ini akan menambahkan sesuatu di sepanjang baris ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4ke URL, yang memberi tahu PHP id sesi yang harus digunakan.

sakabako
sumber
3
Itu juga membuatnya sangat rentan terhadap pencurian sesi :) Masalahnya bukan pada ID sesi yang tidak cocok (mereka, lihat posting saya yang diperbarui), tetapi dengan data yang tidak bergerak di antara domain.
dragonmantank
Setuju, ini sangat rentan meninggalkan ID sesi dalam string kueri.
Ian Jamieson
4
Cookie juga dikirim sebagai teks biasa, ini tidak membuka jalan yang belum terbuka. Saya tidak mengatakan ini solusi yang baik, tetapi tidak kalah amannya dengan menggunakan cookie.
sakabako
1
Ini kurang aman dalam arti bahwa pengguna mungkin (diperdaya) membagikan URL mereka dan dengan demikian membagikan ID sesi aktif mereka. Sangat kecil kemungkinannya bagi pengguna untuk membagikan cookie ID sesi mereka tanpa disadari.
Bastiaan ten Klooster