2009-06-06 134 views
6

我已經創建了一個登錄系統在PHP登出功能等,但我需要會議在窗口關閉銷燬。這需要「即時」或儘可能快地將用戶狀態更改爲離線。我真的不想在會話中設置時間,因爲這對於用戶必須始終登錄而言很煩人。關閉窗口會話?

歡迎任何建議,謝謝。 =)

回答

6

默認情況下,PHP發送的所有會話cookie在瀏覽器關閉時都會被刪除。但據我所知,你想在其他瀏覽器上顯示通知。這有點困難,不太好。你必須使用window.onclose事件處理程序,並向服務器發出一個Ajax請求(我相信它應該是一個同步請求)以發出窗口關閉的信號。同步呼叫不是那麼好...

另一方面,其他瀏覽器將不得不拉動服務器與其他Ajax請求,以查看某個用戶何時註銷。

所有這些Ajax請求都會產生一個醜陋的解決方案。

更新:

由於Thorarin和喬納森Fingland說,有可能是問題的多個窗口(不是標籤,如在窗戶沒有標籤window.onclose火災),但我相信有這個問題的解決方案太。如果第一個窗口設置了一個cookie number_of_windows = 1,對於每個打開的窗口,該值都會遞增,然後在窗口關閉時,只有當number_of_windows等於1時才觸發Ajax請求,否則它只會遞減number_of_windows

更新2:

上述解決辦法,事實上,有多個打開的選項卡的麻煩。我在想如何緩解這一點。

更新3:

OK,我想通了某種形式的解決方案,但它不是在IE6的工作,不知道其他的IE版本。下面的代碼片段記錄了打開的窗口和標籤的數量(IE之間沒有實時更新document.cookie,但我相信它可以通過一些IE專有功能來解決)。然後在每個頁面上卸載,這意味着甚至可以在同一網站上從一個頁面到另一個頁面進行導航,該腳本檢查以查看有多少個打開的窗口。如果它是唯一打開的窗口/選項卡,則會發出Ajax請求。這是解決方案的第一部分。現在,第二部分。

在服務器端,Ajax調用請求的腳本應該更新數據庫中的某些條目,說用戶可能已關閉該頁面。你如何判斷她是不是隻訪問你網站上的一個新頁面?很簡單,在每一頁訪問中,您檢查數據庫是否可以註銷該會話的值,並且如果您將它們標記爲false(用戶已登錄),則用戶會一直註銷數據庫(true旗)。

這很麻煩,但它是我想到的唯一解決方案,因爲我無法確定在JavaScript中重新加載頁面或類似內容。另外,我沒有做廣泛的測試,更多的是一個想法。無論如何,我不會推薦這個解決方案。對每個更改頁面的Ajax請求都是過度殺毒,並且在服務器上的命中數字翻倍,而不計算其他瀏覽器所做的輪詢。

以下是摘錄。順便說一句,bakery.js是document.cookie的一個小包裝。你可能會發現its source here on github

<!DOCTYPE html> 

<html> 
<head> 
<meta charset="UTF-8"> 
<title></title> 
<script type="text/javascript" src="bakery.js"></script> 
<script type="text/javascript"> 
var logout = function() { 
    var xhr = new XMLHttpRequest; 
    xhr.open("GET", "logout.php", false); 
    xhr.send(null); 
}; 

window.onload = function() { 
    var winNumber = parseInt(IGS.Bakery.getCookie("winNumber"), 10) || 0; 
    IGS.Bakery.setCookie("winNumber", winNumber + 1); 
}; 

window.onunload = function() { 
    var winNumber = parseInt(IGS.Bakery.getCookie("winNumber"), 10) || 0; 
    IGS.Bakery.setCookie("winNumber", winNumber - 1); 

    if (winNumber === 1) { 
     logout(); 
    } 
}; 

var showCookies = function() { 
    alert(IGS.Bakery.getCookie("winNumber")); 
}; 
</script> 
</head> 
<body> 

<a href="#" onclick="showCookies();">show</a> 

</body> 
</html> 

忘了提。 window.onclose不是跨瀏覽器的。

+1

也不正如在thorarin的例子中指出的那樣可靠地工作,因爲多個窗口/標籤可以在同一個站點上打開。第一個關閉會導致會話被殺 – 2009-06-06 13:34:08

+0

感謝您的建議 – Elliott 2009-06-06 13:44:39

3

您可以使用JavaScript來實現OnUnload事件,並使用AJAX與離開該站點的用戶進行通信。但是,當他們導航到另一個頁面時也會發生此事件。如果您考慮到多個窗口打開的可能性,您必須實施類似於「如果用戶不在x秒內請求新頁面」的情況,他已離開我的網站,但它不會可靠地工作。

做到這一點的唯一方法是定期對服務器進行AJAX回發,以確保用戶仍在您的頁面上。但它仍然不會立即。

您可以嘗試嘗試使用您要發回的腳本。在響應之前建立一個重要的等待期。當用戶離開您的頁面時,瀏覽器將可能中止正在進行的XmlHttpRequest。您的服務器端腳本可能會註冊客戶端斷開連接,並斷定用戶再次離開...,除非他們繼續加載另一個頁面。

總之,沒有明確的方式做到這一點乾淨的方式。

1

您可以分隔實際登錄的「顯示爲已登錄」的概念。例如,每當用戶請求某個頁面時,您可以將其標記爲「在線」幾分鐘,但您可以設置其實際登錄超時到幾個小時。在這種方案中,如果用戶離開他們的計算機,該網站會在幾分鐘後將他們顯示爲「離線」,但他們仍然可以在一小時左右返回並且不必重新登錄。