簡體   English   中英

Laravel會話隨機到期

[英]Laravel session expires randomly

我們在我們的網站上遇到過這個問題,我們從用戶那里得到了CSRF錯誤。 會話cookie和會話數據設置為在12小時內過期,會話驅動程序設置為使用Redis。 在我們的調查之后,我們最終成功地模擬了異常情況,所以這里是場景:

用戶在網站上打開兩個不同的頁面,使用Chrome瀏覽器打開“打開上次關閉的標簽”設置。 其中一個頁面上有一個表單(例如登錄),然后用戶在某個時刻退出瀏覽器。 他第二天重新打開瀏覽器(12小時過去,因此會話cookie和會話數據已過期)Chrome嘗試重新加載所有打開的頁面。 它向服務器發送兩個同時發出的請求,而它們都沒有會話cookie。 在服務器端,Laravel為每個會話ID生成兩個不同的會話ID。 Chrome接收它們並覆蓋其他會話cookie上的一個。 一旦用戶嘗試提交表單(例如登錄),它就會在表單會話cookie被覆蓋時生成CSRF錯誤。

我們還有一些AJAX帖子請求,由於這種情況我們失敗了CSRF錯誤。

我想知道Laravel是否能夠以安全的方式為兩個請求生成相同的會話ID。

有沒有人有任何想法我們如何解決這個問題?

PS:我們正在使用laravel 4.1和這個會話配置:

return array(

    'driver' => 'redis',

    'lifetime' => 720,

    'expire_on_close' => false,

    'files' => storage_path().'/sessions',

    'connection' => null,

    'table' => 'sessions',

    'lottery' => array(2, 100),

    'cookie' => 'laravel_session',

    'path' => '/',

    'domain' => '.ourdomain.com',
);

經過我們公司對這個問題的大量調查,我得出了這個結果,我希望它有所幫助,首先這里是我們的環境規范:

  • PHP:5.3.3
  • LARAVEL:4.1
  • 操作系統:服務器上的centos 6和開發環境中的os x mavericks
  • APACHE:2
  • MYSQL:5.6.19
  • REDIS:2.4.10
  • PREDIS:0.8。*

首先,似乎TokenMistmatch異常發生在各種不同的條件下,我幾乎調查了所有這些異常,並且能夠解決其中的一些,一些取決於會話背后的邏輯,一些可能是錯誤。 在下文中,我將解釋我面臨的每種情況。

1.過期會議

假設您已經將會話配置為3個小時,用戶打開表單並出於某種原因離開計算機(獲得一杯咖啡),因此在會話過期3小時后,他嘗試提交表單並獲取令牌例外。 這就是為什么每個人一旦進入同時獲得令牌錯誤,無論應用程序有多穩定,我可以設想兩種方法來防止它,並且他們使用ajax及時更新會話cookie,或者增加會話過期時間相當長的時間。

2.會話過期時的並發請求

有時在第一頁的加載時發生並發請求,例如用戶在chrome上打開了兩個不同的選項卡,當他重新打開時,chrome chrome會同時發送請求,或者您可能在第一頁的加載時有多個並發的ajax請求應用。 所以請注意,會話cookie是在收到第一個響應后收到的,但您可以在此之前發送下一個請求,因此您將在每個請求上獲得一個新會話(新cookie),這可能會導致令牌異常,如果其中一個請求填充表單。 您可以根據它的源來阻止這種情況,例如,如果ajax請求導致問題並且您沒有在ajax響應中使用會話,則可以在第二種情況下禁用發送會話cookie(如果請求是ajax)(單擊多次提交按鈕)一旦提交,您可以簡單地禁用該按鈕。

3.登錄時的並發請求

當登錄發生時,出於安全原因,laravel會更改會話ID,復制會話數據和DESTROYS THE LAST SESSION,因此在登錄並發請求時會出於某種原因說(多次單擊登錄按鈕),以便重新生成會話ID多次和DESTROYS在服務器端最后生成的會話,因為其中一些請求仍然使用先前的會話ID(在服務器端不再存在)它導致重新生成CSRF令牌,請注意通常laravel不如果可以在guest虛擬機(未登錄)會話中找到令牌,則在登錄時重新生成令牌,但在這種情況下,因為guest虛擬機會話被銷毀,因此它將重新生成令牌,並且可能導致其他請求中的令牌異常。使用原始令牌。 另請注意,此問題不僅會導致令牌異常,還會導致用戶在一次請求后被注銷,因為並發請求可以更改登錄的會話。 我在lauminvel代碼中更改了一行,在Illuminate\\Auth\\Guard:updateSession解決了這個問題:

 protected function updateSession($id)
 {
        $this->session->put($this->getName(), $id);

        //$this->session->migrate(true);
        $this->session->migrate()
 }

將true傳遞給會話存儲的migrate方法將導致在遷移后銷毀服務器上的會話,因此現在數據將保留在服務器上並在其到期時間而不是在此請求上銷毀,它將解決問題。 我不知道我們是否可以將其稱為laravel中的錯誤,但我想我們可以為此提出更好的解決方案。

4.瀏覽器

調查日志后發現,其中一些令牌異常是因為用戶的瀏覽器不接受會話cookie,我在iOS Safari上看到的最多,我相信這是我們無能為力的事情。

5. Redis bug

我們服務器上的一些令牌例外是因為redis,因為某些原因,laravel在打開會話時無法從redis服務器讀取會話數據,因此會導致CSRF令牌的重新生成。 它是在我們的服務器上隨機發生的,所以我嘗試更改會話驅動程序,這種類型的異常逐漸消失。 我嘗試過數據庫,apc和文件驅動程序,沒有人產生這個問題。 我還沒有找到導致錯誤的原因,但我認為它可能是redis或predis庫的錯誤。 (如您所知,由於兼容性問題,laravel 4.1未使用最新版本的predis)。

好的,這是我過去兩個月在這個問題上的經歷。 我希望它可能改變你對這個問題的解決方案的觀點,最重要的是令牌異常不會發生,因為一個原因可能是多個問題的結果。 如果您遇到類似事件或者您有新事物,請與我分享。

我已經多次遇到過這個問題,沒有具體原因,Amir也沒有提到過。

清除域cookie適用於我看到的場景。

在我的情況下,這是緩存配置文件的問題。 Laravel創建一個緩存在bootstrap / cache文件夾中的配置文件。 將此config.php文件重命名為其他內容並運行“php artisan cache:clear”

然后運行該網站,它應該工作正常

這可能與這個眾所周知的問題有關

Laravel 5.0 - Asyncronous AJAX請求導致會話變量被覆蓋#7549

如果多個請求嘗試覆蓋會話並且會話文件沒有鎖定,則可能導致會話文件損壞(覆蓋)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM