하위 도메인 간 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);

세션 ID는 정확히 동일하지만 $_SESSION변수를 덤프하면 두 키가 모두 표시되지 않으며 각 도메인 아래에 설정 한 키만 표시됩니다.



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/… . 하지만 여기서 찾았습니다.
— Roman

5
완벽하게 작동합니다! 이것에 대한 연령을 찾고 있습니다. 그것은이었다 $some_name = session_name("some_name");그것을 행한. 감사합니다.
— Kit

4
추가 session_name("domain");는 나에게도 부족한 성분이었습니다. 이러한 세션 설정에 관한 php.net의 문서는 부족합니다. php.net에는 session_set_cookie_params ()에 대한 변경 사항을 적용하기 전에 session.name을 정의해야 함을 나타내는 커뮤니티 게시물이 있습니다.
— David Carroll

3
네. 확인. 좋은 사람은 거기에 나이 동안 서클에서 돌아 다니고 있었다;)
— Daithí

1
참고 ... 라이프 서버에서 작동하려면 브라우저를 닫고 다시 시작해야했습니다. ini_set("session.cookie_domain", ".domain.com");이로 인해 새로 고칠 때마다 새 세션 ID가 생성되는 원인 을 모두 제거하십시오 .
— 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모든 하위 도메인에 대해 설정하십시오 .
  • 기본 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');

작동하지 않았 으며 .com / .local / ... 대신 .localhost를 최상위로 봅니다. (나는 의심합니다)


또한 내 컴퓨터에 대해 수정했습니다-Ubuntu 14.04
— dennis

3

확인했습니다. 조레온 의 대답이 맞습니다. 평판이 충분하지 않아 댓글을 달 수 없어 여기에 댓글을 올립니다.

구성 파일에서 상수를 정의하십시오. 변경하려는 경우 전체 파일을 수정할 필요가 없습니다.

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

세션 이름은 숫자로만 구성 될 수 없으며 적어도 하나의 문자가 있어야합니다. 그렇지 않으면 매번 새 세션 ID가 생성됩니다.

다음 코드를 사용하여 세션 사용을 시작하십시오.

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

Joel이 제안한 것처럼 OpenID와 같은 것을 원하지 않지만 여러 도메인에서 세션 데이터에 액세스하고 싶다는 생각이 들었습니다.

이 문제에 대한 해결책으로 생각할 수있는 유일한 가능성은 세션 데이터를 데이터베이스에 저장하고 해당 데이터베이스에서 꺼내는 것입니다.


맞습니다. 인증은 제가하고 싶은 일의 일부이지만 사용자가 작업하는 동안 저장되는 세션 데이터에도 관심이 있습니다.
— dragonmantank 2009-06-30


0

다른 버전의 PHP에 대해서는 말할 수 없지만 5.6.6에서는 파일 의 session.cookie_domain값을 설정하기 만하면 php.iniiPage의 모든 하위 도메인이 동일한 세션 변수 집합을 공유 할 수 있습니다.

테스트를 위해 브라우저에서 도메인과 관련된 기존 쿠키를 모두 제거해야합니다.

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

위의 모든 답변을 읽었으며 내 답변이 인터넷 검색을하는 사람들에게 도움이된다고 생각합니다.

  • 브라우저가 (도메인 및 하위 도메인의) 서버로 세션 쿠키를 다시 전송하는지 확인하고 세션 쿠키 도메인을 .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

0

사용하다 :

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

-2

빠르고 더러운 해결책은 리디렉션에 이것을 사용하는 것입니다.

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

이렇게하면 ?PHPSESSID=etnm7kbuf5lg0r6tv7je6ehtn4URL 행을 따라 무언가가 추가 되어 PHP에 사용해야하는 세션 ID를 알려줍니다.


3
또한 세션 도난에 매우 취약합니다. :) 문제는 세션 ID가 일치하지 않는 것이 아니라 (내 업데이트 된 게시물 참조) 데이터가 도메인간에 이동하지 않는 것입니다.
— dragonmantank 2009-06-30

동의합니다. 이것은 쿼리 문자열에 세션 ID를 남겨 두는 매우 취약합니다.
— Ian Jamieson 2013

4
쿠키는 일반 텍스트로도 전송되며 아직 열려 있지 않은 경로는 열리지 않습니다. 좋은 해결책이라고 말하는 것은 아니지만 쿠키를 사용하는 것보다 덜 안전합니다.
— sakabako

1
사용자가 URL을 공유 (속임)하여 활성 세션 ID를 공유 할 수 있다는 점에서 보안 수준이 떨어집니다. 사용자가 자신도 모르게 세션 ID 쿠키를 공유 할 가능성이 훨씬 적습니다.
— Bastiaan ten Klooster
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.