Phiên PHP trên các miền phụ


92

Tôi đang cố gắng thiết lập như sau:

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

Nếu người dùng truy cập sub1.example.comhoặc sub2.example.comvà họ chưa đăng nhập, họ sẽ được chuyển hướng đến auth.example.comvà có thể đăng nhập.

sub1.example.comsub2.example.comlà hai ứng dụng riêng biệt nhưng sử dụng cùng thông tin đăng nhập.

Tôi đã thử thiết lập những điều sau trong php.ini của mình:

session.cookie_domain = ".example.com"

nhưng dường như nó không truyền thông tin từ miền này sang miền khác.

[Biên tập]

Tôi đã thử những cách sau:

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

Các ID phiên hoàn toàn giống nhau nhưng khi tôi loại bỏ $_SESSIONbiến, nó không hiển thị cả hai khóa, chỉ là bất kỳ khóa nào tôi đặt trong mỗi miền.


Bạn cũng phải kích hoạt nó trong mã của mình, hãy xem http://us2.php.net/manual/en/
Chức năng.session

1
Tôi có thiết lập gần như tương tự (tôi đặt miền cookie phiên bằng lệnh gọi thành "session_set_cookie_params") và nó hoạt động tốt.
Milen A. Radev

Đây là chức năng tốt đẹp mà công trình stackoverflow.com/questions/2835486/...
boksiora

Câu trả lời:


134

Tôi không biết sự cố còn tồn tại hay không, nhưng tôi vừa gặp phải sự cố tương tự và đã giải quyết nó bằng cách đặt tên phiên trước khi gọi session_set_cookie_params():

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

Tôi không có gì thay đổi trong tôi php.ininhưng bây giờ mọi thứ đang hoạt động tốt.


10
Tôi xác nhận, nó giải quyết được vấn đề. Tôi mệt mỏi khi nhận được câu trả lời của mình ở đó: stackoverflow.com/questions/4948340/… . Nhưng tôi đã tìm thấy nó ở đây.
Roman

5
Hoạt động hoàn hảo! Đã tìm kiếm độ tuổi cho điều này. Đó là $some_name = session_name("some_name");điều đã làm điều đó. Cảm ơn bạn và ủng hộ.
Kit

4
Bổ sung session_name("domain");là thành phần còn thiếu đối với tôi. Tài liệu trên php.net về các cài đặt phiên này còn thiếu. Có những bài đăng cộng đồng trên php.net chỉ ra rằng session.name cần được xác định trước khi có thể áp dụng các thay đổi đối với session_set_cookie_params ().
David Carroll

3
Vâng. đã xác nhận. tuyệt vời là một người đã đi vòng quanh các vòng tròn cho các lứa tuổi ở đó;)
Daithí

1
LƯU Ý ... đã phải đóng trình duyệt của tôi và khởi động lại để trình duyệt hoạt động trên máy chủ cuộc sống. Bỏ qua bất kỳ ini_set("session.cookie_domain", ".domain.com");nguyên nhân nào khiến nó tạo id phiên mới sau mỗi lần làm mới.
Daithí

24

Một thứ có thể ngăn cản việc đọc dữ liệu phiên một cách bí ẩn trên một miền phụ, mặc dù cookie đã được đặt chính xác .example.comlà bản vá PHP Suhosin. Bạn có thể định cấu hình mọi thứ một cách chính xác, theo các ví dụ trong câu hỏi, và nó có thể không hoạt động.

Tắt các cài đặt phiên Suhosin sau và bạn đã trở lại công việc kinh doanh:

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

5

Hãy thử sử dụng:

session.cookie_domain = "example.com"

Thay vì:

session.cookie_domain = ".example.com"

Lưu ý khoảng thời gian bị thiếu ở đầu.

Tuy nhiên, hãy cẩn thận khi sử dụng cái này vì nó không được hỗ trợ bởi tất cả các trình duyệt.


9
Những trình duyệt nào không được hỗ trợ?
gawpertron

10
hỗ trợ trình duyệt nào ở đây? đây là một hành động phía máy chủ.
Kuf

4

Gặp sự cố chính xác này - tôi muốn các giá trị phiên được tạo trên x.example.local có sẵn trên example.local và ngược lại.

Tất cả các giải pháp tôi tìm thấy đều cho biết thay đổi miền Phiên bằng cách sử dụng php_value session.cookie_domain .example.localtrong .htaccess (hoặc qua php.ini hoặc qua ini_set).

Điểm bắt được là tôi đã đặt session.cookie_domaincho tất cả các miền phụ (cho đến nay vẫn ổn) nhưng cũng cho miền chính. Đặt miền session.cookie_domaintrên miền chính rõ ràng là không.

Về cơ bản cách nó hoạt động đối với tôi:

  • đặt session.cookie_domaincho TẤT CẢ CÁC SUBDOMAINS.
  • không đặt nó cho DOMAIN chính

Ồ có, vui lòng đảm bảo miền có TLD (trong trường hợp của tôi là .local). Giao thức Http không cho phép lưu trữ cookie / phiên trên miền không có .tld (tức là localhost sẽ không hoạt động, nhưnguff.localhost thì có).

CHỈNH SỬA : Đồng thời đảm bảo rằng bạn luôn xóa cookie của trình duyệt trong khi thử nghiệm / gỡ lỗi các phiên trên các miền phụ. Nếu bạn không làm vậy, trình duyệt của bạn sẽ luôn gửi cookie phiên cũ mà có thể chưa đặt cookie_domain chính xác. Máy chủ sẽ phục hồi phiên cũ và do đó bạn sẽ nhận được kết quả âm tính giả. (trong nhiều bài viết có đề cập đến việc sử dụng session_name ('thứ') để có cùng hiệu ứng)


3

Tôi đã giải quyết nó như thế này

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

Vì tôi đang làm việc trên localhost

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

không hoạt động , nó coi .localhost là cấp trên cùng thay vì .com / .local / ... (tôi nghi ngờ)


Cũng đã sửa nó cho máy của tôi - Ubuntu 14.04
dennis

3

Tôi đã xác nhận. câu trả lời của joreon là đúng. Tôi không thể bình luận vì danh tiếng của tôi không đủ nên tôi đăng bình luận của tôi ở đây.

Xác định hằng số trong tệp cấu hình. Nếu bạn muốn thay đổi nó, không cần phải sửa đổi toàn bộ tệp.

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

Tên phiên không được chỉ bao gồm các chữ số, phải có ít nhất một chữ cái. Nếu không, một id phiên mới được tạo mỗi lần.

Sử dụng mã sau để bắt đầu sử dụng phiên

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

Tôi đang sử dụng chức năng này:

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

Sử dụng nó trên mọi miền / miền phụ:

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

Đường dẫn cho session.save_pathcó thể khác nhau đối với trường hợp của bạn nhưng nó phải giống nhau trên mọi miền / miền phụ. Nó không phải lúc nào cũng đúng theo mặc định.


1

Sử dụng cái này, nó hoạt động:

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

cái này có vẻ như nó đang cài đặt cookie cho tld ... hay tôi thiếu cái gì đó?
chacham

1

Tên miền phụ và tên miền gốc Sử dụng kết hợp phiên cookie

Tài nguyên: http://php.net//manual/tr/ Chức năng.session-set-cookie-params.php

Tôi đã thử nghiệm các tác phẩm

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

example.com/sessionview.php // 123

- Mã

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

Tôi hiểu rằng bạn không muốn một thứ gì đó giống như OpenID, như Joel đang đề xuất, nhưng bạn muốn có quyền truy cập vào dữ liệu phiên trên nhiều miền.

Khả năng duy nhất mà tôi có thể nghĩ đến như một giải pháp cho vấn đề đó là lưu trữ sessiondata trong một cơ sở dữ liệu và kéo nó ra khỏi cơ sở dữ liệu đó.


Đúng vậy, mặc dù xác thực là một phần của những gì tôi muốn làm, nhưng tôi cũng quan tâm đến dữ liệu phiên được lưu trữ trong khi người dùng đang làm việc.
dragonmantank,


0

Tôi không thể nói cho các phiên bản PHP khác, nhưng trong 5.6.6, chỉ cần đặt session.cookie_domaingiá trị trong php.initệp đã thực hiện mẹo cho phép tất cả các miền phụ của tôi trên iPage chia sẻ cùng một tập hợp các biến phiên.

Đảm bảo xóa mọi cookie hiện có liên quan đến miền của bạn khỏi trình duyệt để kiểm tra.

session.cookie_domain = '.yourdomainname.example'

Ồ, không biết nó có tạo ra sự khác biệt nào không nhưng tôi cũng đang sử dụng tự động khởi động phiên.

session.auto_start = 1

0

Chỉ cần thử sử dụng mã sau ngay session_start()phương pháp trên

$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

Tôi đã đọc tất cả các câu trả lời ở trên, tôi nghĩ câu trả lời của tôi hữu ích cho những người đang tìm kiếm điều này:

  • đảm bảo trình duyệt gửi cookie phiên trở lại máy chủ (của miền và miền phụ), đặt miền cookie phiên làm .example.com.

  • Đảm bảo PHP tìm đúng "mục tiêu" để khôi phục biến phiên:

    • Nếu miền và miền phụ trỏ đến cùng một máy (có thể là các máy chủ ảo khác nhau), hãy đảm bảo rằng session_save_pathtất cả đều giống nhau (tôi đã thử nghiệm)
    • Nếu miền và miền phụ trỏ đến các máy khác nhau, thì bộ nhớ chung (như cơ sở dữ liệu) là tốt nhất để lưu và khôi phục dữ liệu phiên (tôi chưa thử nghiệm). Sử dụng session_set_save_handlerđể làm điều đó.

0

Tôi biết điều này đã cũ nhưng điều này hoạt động tốt đối với tôi với nhiều miền và miền phụ trên cùng một hộp.

<?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
Bạn đang trả lời câu hỏi nào? Và làm thế nào để điều này cải thiện / nâng cao trên 9 câu trả lời khác?
random_user_name 28/10/12

0

Sử dụng :

session_name("put_a_session_name");
session_start([
  "cookie_domain" => ".example.com",
  "cookie_path" => "/"
]);

-2

Một giải pháp nhanh chóng và hiệu quả là sử dụng điều này cho chuyển hướng của bạn:

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

điều này sẽ thêm một cái gì đó dọc theo các dòng của ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4URL, nó cho PHP biết id phiên mà nó sẽ sử dụng.


3
Nó cũng khiến nó rất dễ bị đánh cắp phiên :) Vấn đề không phải là ID phiên không khớp (chúng, hãy xem bài đăng cập nhật của tôi), mà là dữ liệu không di chuyển giữa các miền.
dragonmantank

Đồng ý, điều này rất dễ bị tổn thương khi để lại ID phiên trong chuỗi truy vấn.
Ian Jamieson

4
Cookie cũng được gửi dưới dạng văn bản thuần túy, điều này không mở ra bất kỳ con đường nào chưa được mở. Tôi không nói đó là một giải pháp tốt, nhưng nó an toàn không kém so với việc sử dụng cookie.
sakabako

1
Nó kém an toàn hơn theo nghĩa là người dùng có thể bị (lừa) chia sẻ URL của họ và do đó chia sẻ ID phiên hoạt động của họ. Ít có khả năng người dùng vô tình chia sẻ cookie phiên ID của họ.
Bastiaan ten Klooster
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.