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