AJAXでクロスドメインセッションは使えない

サイトを越えてデータの読み書きを行うのに、AJAX+JSONという便利な仕組みがあります。
* 一番簡単なJSONP+jQuery超入門 >> [id:rikunora2:20100727]
しかしながら、セキュリティのため、データの読み書きには様々な制限が施されています。
今回、ドメイン間をまたがって PHPのセッション変数が自由に使えないことがわかったので、メモしておきます。

以下のような HTMLと PHPファイルを用意して、セッションの挙動を確かめてみました。
HTMLファイル側では、jQueryajax関数を利用して PHPを呼び出しています。

* test.html


<html>
<head>
<script type="text/javascript" src="js/jquery-1.4.2.min.js" />
<script type="text/javascript">
function doJsonp(){
// サイトAにあるカウンター、test.phpを呼び出す.
$.ajax({
dataType: "jsonp",
url: "http://Site-A/test.php",
success: function (data) {
$("#message").empty();
$("<p/>")
.text(data.count)
.appendTo("#message");
}
});
}
</script>
</head>
<body>
<form name="form1" action="">
<input type="button" value="Click me!" onclick="doJsonp();"/>
</form>
<div id="message" />
</body>
</html>

一方、PHPファイルには、セッション変数を使ったカウンターが仕組まれています。
* test.php -- Site-A 上に置かれている.


<?php
header("Content-Type: application/json; charset=UTF-8");
session_start();

$callback = $_GET['callback']; // コールバック関数名

if( ! isset($_SESSION['count']) ){ // 'count'セッションを付ける.
$_SESSION['count'] = 0;
}
$cnt = ++ $_SESSION['count'];

echo $callback ;
echo '({"count": "'. $cnt .'"});';
?>

上の HTMLと PHPを、どちらも同一のドメイン内に置けば、カウンターは問題なく動作します。

ところが、PHPをとあるドメイン(サイトA)に置いたまま、HTMLファイルだけを別のドメイン(サイトB)に持って行くと、
カウンタは動作せず、常にカウント数=1のままになります。
要は、ドメイン間をまたがってPHPのセッション変数は使えない、ということなのです。

このセッションを使ったカウンター、ブラウザ依存で、動作する場合と、しない場合があります。
Windows XP上で試したところ、こんな風になりました。
 ・I.E 8.0    -- × N.G
 ・Safari 5.0.1  -- × N.G
 ・FireFox 3.6.8 -- ○ O.K
 ・Chrome 5.0   -- ○ O.K

さて、サイトBにアクセスして動作しなかったカウンターなのですが、
いったんサイトA上に置かれている test.phpに直接アクセスして、
その後サイトBの test.htmlにアクセスしに行くと、今度は問題なくカウンターが動き出します。
なぜこうなるのか?
その秘密は、PHPセッションの一意性を保っているCookieの挙動にあります。

サイトAに直接アクセスした場合、サイトAから発行されたCookieは、問題なくブラウザに保存されます。
ところが、サイトB経由で間接的にサイトAにアクセスした場合、
サイトAの発行したCookieは、ブラウザに保存されません。
(この保存の仕方がブラウザ毎に異なっているのです。I.Eは保存せず、Firefoxは保存します。)
I.Eの場合、もともとサイトAが発行したCookieであっても、
ブラウザ側ではサイトBが発行したCookieとして保存していました。
サイトAの側から見れば、自分の発行したCookieが付いていないので、
いつでも新規セッションなのだと解釈し、カウンターが1のままになる、という訳なのです。

もし1度でも直接サイトAにアクセスすれば、サイトAの発行したCookieがブラウザに保存されます。
すると、それ以降は問題なくカウンターが動き出すのです。

以上、サイト間をまたがったCookieの挙動は、ブラウザ依存のややこしい動作をします。
サイト間にまたがってセッションを利用する際には、この辺の仕組みをよく考えないといけません。