搜尋

首頁  >  問答  >  主體

在 Laravel 中,是否可以根據存取的路由動態延長會話時間?

<p>標題幾乎概括了我的問題。 </p> <p>我工作的公司有一個Laravel 應用程序,其中<code>config/session.php</code> 上的會話時間設定為<strong>120 分鐘</strong>後過期,這是預設行為我們不想改變這個值。 </p> <p>但係統有一個特定功能,使用者必須回答大量的表格/問卷,<strong>如果使用者打字速度慢,可能需要超過3 或4 個小時才能完成</strong>在提交之前返回重新考慮一些答案。 </p> <p>問題是,有些使用者仍未完成所有問題,會話過期使他們失去進度,有時他們只有在幾分鐘後切換到問題的「下一頁」時才發現會話過期。我們考慮過保存已經填寫的數據,但即使我們用AJAX 呼叫持久化內容,將已經填寫的部分保存到資料庫中,在回答表單時需要再次登入仍然是一個糟糕的用戶體驗,因為他們需要遵循無論如何,再次連結進入表單頁面。由於會話過期,我們收到了很多客戶的投訴。 </p> <p>最好的方案是在<code>FormController.php</code> 上建立某種函數,當使用者進入表單頁面或其他一些特定路由時,我們會執行類似<code>session()的操作->extendSessionInMinutes(360)</code>。我做了一些研究,但在 Laravel 文件(請注意我們使用的是 <code>Laravel 8.1</code>)或 Stackoverflow 上找不到類似的內容。本週閱讀了有關此主題的許多內容,例如有關創建新中間件的解決方案,該中間件根據用戶角色或類似內容提供不同的會話生命週期,但此選項對我們來說沒有用。 </p> <p>我正在開發一個解決方案,該解決方案將使用類似的解決方案在會話上添加<strong>新變數</strong> <code>session()->put('time_to_logout' , now()->addHours( 2))</code> 了解會話達到2 小時的確切時間,因此我可以<strong>將<code>SESSION_LIFETIME</code></strong> 的預設值的生命週期增加到5 小時,並添加JS 函數每30 分鐘檢查一次,是否需要登出並將使用者重新導向至登出頁面,如果他在表單頁面上,我們將停止檢查。 </p> <p>但我認為這實際上不是一個好的解決方案,但我似乎無法考慮另一個解決方案。有沒有辦法以某種方式延長會話時間來完成我想要的事情?或者在不影響用戶的情況下重新創建會話(<em>我敢打賭,這會弄亂表單上的CSRF 令牌</em>),並且在他繼續填寫表單的同時,用2 個小時以上的時間無縫地重新創建會話,沒有註意到任何變化? </p> <p>建立會話後,無法變更其過期時間嗎?是否有某種 PHP 函式庫可以幫助我,而無需更改太多 Laravel 預設會話相關功能? </p> <p><em>提前感謝您的任何意見。 </em></p>
P粉019353247P粉019353247493 天前689

全部回覆(1)我來回復

  • P粉978551081

    P粉9785510812023-09-02 00:13:22

    是的,可以。並且您需要執行以下操作-

    1. 只有透過中間件才能動態變更會話生命週期。因為透過任何控制器(沒有中間件)更改它都不會更改會話值,因為會話已經啟動。所以你需要一個中間件。就像下面這樣-
    namespace App\Http\Middleware;
    
    class ChangeSessionValueDynamically
    {
        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, $next)
        {
            $lifetime = 1440; /* Minutes*/
            config(['session.lifetime' => $lifetime]); /* Helper function */
            return $next($request);
        }
    }
    1. 之後,您需要將該中間件新增至 app/Http/Kernel.php 檔案中的 $middlewarePriority 陣列中,該檔案必須在 Laravel 執行自己的「StartSession」中間件之前執行。就像下面這樣-

    \Illuminate\Session\Middleware\StartSession::class, 之前加入 \App\Http\Middleware\ChangeSessionValueDynamically::class,

    /**
         * The priority-sorted list of middleware.
         *
         * This forces non-global middleware to always be in the given order.
         *
         * @var array
         */
        protected $middlewarePriority = [
         ....
         ....
            \App\Http\Middleware\ChangeSessionValueDynamically::class
            \Illuminate\Session\Middleware\StartSession::class,
         ....
         ....   
        ];
    1. 提供 \App\Http\Middleware\ChangeSessionValueDynamically::class 的別名,如下圖 -
    /**
        * The application's route middleware.
        *
        * These middleware may be assigned to groups or used individually.
        *
        * @var array
        */
       protected $routeMiddleware = [
        ....
        ....
           'dynamic_session' => \App\Http\Middleware\ChangeSessionValueDynamically::class,
        ....   
        ....
       ];
    1. 將該中間件包含在路由中,如下所示 -
    A) For Group Routes- 
    Route::group([.., 'middleware' => ['dynamic_session', ..]], function () {
        ..
        Route::get('route_1', ['uses' => 'AbcController@index', 'as' => 'abc.index']);
        ..
    }
    
    B) OR For single Route-
    Route::get('route_1', ['uses' => 'AbcController@index', 'as' => 'abc.index'])->middleware('dynamic_session');

    回覆
    0
  • 取消回覆