首页  >  问答  >  正文

在 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粉019353247437 天前612

全部回复(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
  • 取消回复