2010年9月16日 星期四
SESSION / COOKIES in IFRAME 解決辦法
Header append P3P 'CP="OURPOLICYINFO"'
ASP:
Response.AddHeader "P3P", "CP=CAO PSA OUR"
php:
header('P3P: CP=CAO PSA OUR');
ASP.NET
通過在代碼上加
Response.AddHeader("P3P", "CP=CAO PSA OUR")
或者在Window服務中將ASP.NET State Service 啟動。
JSP:
response.setHeader("P3P","CP=CAO PSA OUR")
這樣就可以抓取的到 session / cookie
[引用]實現多域名下共用一個SESSION
要實現多域名共享session,首先就得瞭解SESSION的運行機制。基本概念我就不說了。
session是這樣運行的:
用戶A訪問站點Y,如果站點Y執行了session_start();(以下假定session_start()總是存在)那麼會產生一個 session_id,這個session id一般會以COOKIE的形式保存到用戶A(我們可以通過在php.ini裡設置session.use_only_cookies為1,強制 SESSION ID必須以COOKIE傳遞。)。這時候SESSION ID表現為$_COOKIE['PHPSESSID'];(PHPSESSID可用session_name()函數來修改)
用戶A接著訪問,這個session id($_COOKIE['PHPSESSID'])就會在A每次訪問Y的時候傳送到站點Y。
在站點Y上,會有這麼一個目錄,是用來保存SESSION的實際數據的。站點Y接收到session id,然後通過session id,來獲得與SESSION數據的關聯,並返回SESSION數據。
可能聰明的你已經想到了,既然服務器端和客戶端之間的SESSION是通過一個SESSION ID來聯繫,並且SESSION數據是以普通文件的形式保存在一個特定的文件夾裡。
那麼我們要實現不同域名,只需要滿足以下兩個條件:
* 1)不同域名的SESSION數據目錄統一到一起,或者同步更新。
* 2)對同一個客戶,使用統一的一個SESSION ID
第一個條件的實現。
如果是同一台服務器,就不需要進行任何設置了。
如果是集群/分佈式的,那麼我想也不需要我來說了。。能做分佈式應用的,在目錄共享方面的經驗應該比我豐富。我也沒有進行過多服務器的測試,主客觀條件的原因都有。
我在這裡主要是想說一下第二個條件——使不同的域名,擁有統一的SESSION ID。
那我們應該怎麼統一呢?
首先必須在不同域名之間傳遞這個SESSION ID,且由於 cookie必須是針對域名的,所以傳遞動作是由客戶端來完成。如果傳遞過程不是由客戶端來完成,那麼接受傳遞的域名就不知道針對的是哪個客戶。
其次就是修改接受傳遞的域名下的SESSION ID。
如何傳遞:
HTML裡,我們可以使用很多種方法。例如
iframe
<iframe src=」"></iframe>
或者.js
<script type=」text/javascript」 src=」"></script>
或者是一個img html元素
<img src=」" />
只要能調用某個地址,就行。
在wml裡,由於wml script的特點,我們無法使用script這樣的形式來調用,而wml裡也沒iframe..但是我們還是可以通過img來實現傳遞的。
如何修改:
既然SESSION ID一般情況下是通過COOKIE來傳遞,那麼我們只需要通過傳遞$_COOKIE['PHPSESSID'];即可。但是如果PHPSESSID被 session_name改變了,我們又得修改setcookie中的PHPSESSID..這樣就會變得很麻煩。。所以我們可以選擇一個session 特有的函數session_id來修改$_COOKIE['PHPSESSID'];
需要注意的幾點:
* 如果session.use_only_cookies為0(PHP默認),那麼session id有可能會以url或其他形式傳遞
* session_id()和session_name必須在session_start()前使用
以下是我寫的一個簡單的實現多域名的類。如果上面的看不太明白,可以看看我的這個多域名類。這個類是在HTML下以iframe形式實現的。
<?php
class mdSession
{
/*
使用:
服務器A,服務器B,在A的index.php登陸,在B裡建立一個接收SESSION的文件,例如ses_get.php
A的index.php做如下修改
最開始加上session_start();
<body></body>裡,任意一個地方寫上:mdSession::_set('B/ses_get.php')
而ses_get.php則在開頭寫上mdSession::_get();
@作者:surfchen@gmail.com http://www.surfchen.org/
*/
function mdSession()
{
}
function set($urls)
{
if (!is_array($urls))
{
$urls=array($urls);
}
foreach ($urls as $value)
{
echo '<span style="position:absolute;visibility:hidden"><iframe src="'.$value.'?'.session_id().'"></iframe></span>';
}
return true;
}
function get()
{
session_id($_SERVER['QUERY_STRING']);
session_start();
return true;
}
function _set($urls)
{
$obj=new mdSession();
return $obj->set($urls);
}
function _get()
{
$obj=new mdSession();
return $obj->get();
}
}
?>
2008年6月25日 星期三
[引用]非mmcache!Memcached的應用:多網站伺服器 PHP 共享 Session
請注意是 Memcached 不是 mmcache,很多人搞不清楚他們兩個的不同!多半玩過 PHP 的人大概都聽過 mmcache,它是一個預編譯緩衝的 PHP 加速程式,能夠提升 PHP 的執行效能。但很少人聽過 Memcached ,因為大多人乍看之下都以為它是mmcache,使得它沒什麼機會介紹自己。事實上,若您正打算架構一個真正高負載的大型網站系統,你需要瞭解的並不是 mmcache,而是 memcached。
Memcached 是什麼?顧名思義,他是由記憶體(Memory)和暫存(cache)所組合起來的常駐程式(Daemon),你也可以稱它為『暫存伺服器』。 Memcached 能提供一個暫存資料的服務,透過網路供其他電腦使用。Memcached 有什麼用途?最常見的應用就是在網站伺服器的叢集,它能讓許多的網站伺服器 Session 互相流通使用。如果你正在傷透腦筋煩惱這一點,恭喜你找到解決方法了!
想 要在網站伺服器的叢集中,多網站伺服器 Session 互相流通使用,首先你必須將 Memcached 架起來當 Session 分享伺服器,這邊建議你使用大的記憶體,最好是能多大就有多大,因為 Memcached 並不會以硬碟當資料暫存,而是會完全跑在記憶體上,所以若記憶被用完了,Memcached 就會無法再存放更多資料。
接 著,你必須修改 PHP 的 Session Save Handler,讓 PHP 懂得利用 Memcached Server 存放 PHP 的 Session 資料並能從 Memcached Server 取出 Session 的資料。PHP提供了 session_set_save_handler() 函式讓我們能輕易修改 Session Save Handler ,以下是我修改後的 PHP 程式碼,你必須在呼叫 session_start() 之前使用:
define("SHARED_SESS_TIME", 3600); // Timeout
// Session Class by Fred
class Shared_Session
{
function init()
{
ini_set("session.use_trans_sid", 0);
ini_set("session.gc_maxlifetime", SHARED_SESS_TIME);
ini_set("session.use_cookies", 1);
ini_set("session.cookie_path", "/");
ini_set("session.cookie_domain", ".yourdomain.com.tw");
session_module_name("user");
session_set_save_handler(
array("Shared_Session", "open"),
array("Shared_Session", "close"),
array("Shared_Session", "read"),
array("Shared_Session", "write"),
array("Shared_Session", "destroy"),
array("Shared_Session", "gc")
);
}
function open($save_path, $session_name) {
return true;
}
function close() {
return true;
}
function read($sesskey) {
global $memcache;
return $memcache->get($sesskey);
}
function write($sesskey, $data) {
global $memcache;
$memcache->set($sesskey, $data, SHARED_SESS_TIME);
return true;
}
function destroy($sesskey) {
global $memcache;
$memcache->delete($sesskey);
$memcache->flush_all();
return true;
}
function gc($maxlifetime = null) {
return true;
}
}
$GLOBALS["memcache"] = memcache();
$GLOBALS["memcache"]->add_server("192.168.1.1", 11211);
$GLOBALS["memcache"]->add_server("192.168.1.2", 11211);
Shared_Session::init();
其中粗字體的部分,是要特別修改的地方:
- 3600 是 Session 的生命週期﹝以秒為單位﹞,這應該不用再做太多解釋。
- yourdomain.com.tw 是你的網域名稱:想像一個情況若是 Loadbalance 在用戶第一次連線分配用戶到A伺服器,第二次連線分配給同一用戶到B伺服器,會導致 B 伺服器無法透過 cookies 取得 A 伺服器分配給用戶的 session_id,因為 cookies 無法跨網域存取,解決方法是必須修改 cookies 的網域設定,讓 www1.yourdomain.com.tw、www2.yourdomain.com.tw、www3.yourdomain.com.tw...等 等,都可以共同存取同一個 cookies ,以取得同一個 session_id,故此時你必須設定成為『.yourdomain.com.tw'。
- 192.168.1.1 這是你的 Memcached Server 的 IP 位置,這裡值得提的是 add_server() 方法,你可以有多行設定許多 IP 做 Loadbalance 負載分配,前面也講到 Memcached 是純粹使用記憶體,若其中一台機器記憶體滿了,本方法可以從中找到另一台可用的機器使用。故你可以建立一個 Memcached 的叢集來處理 Session。
因為我偷 懶, Memcached 的安裝方法就沒寫了,去求助 google 大神,它應該會告訴你更多詳細的安裝資料。其實 Memcached 除了可應用在 Session 共享上,也可以應用在資料庫的資料暫存緩充,降低SQL Server負擔以提升速度。Memcached多好用?就看你怎麼用了!
該作者網站:Fred's blog