【问题标题】:Laravel session timeout, extra logout codeLaravel 会话超时,额外的注销代码
【发布时间】:2020-03-20 17:10:47
【问题描述】:

底线:

如何在会话超时时注销用户?


详细问题:

我有一个 Laravel 5.6.* 应用程序,该项目要求用户在用户空闲时注销。我已经尝试过这里给出的解决方案,但没有一个对我有用。

然后我偶然发现了这篇文章: https://laravel-tricks.com/tricks/session-timeout-for-logged-in-user 并没有成功。


我想要什么:

在会话超时时自动注销用户。在注销之前,将Users 表上的is_logged_in 属性设置为false0。我如何做到这一点?


到目前为止我尝试过的代码:

session.php

/*
 |--------------------------------------------------------------------------
 | Session Lifetime
 |--------------------------------------------------------------------------
 |
 | Here you may specify the number of minutes that you wish the session
 | to be allowed to remain idle before it expires. If you want them
 | to immediately expire on the browser closing, set that option.
 |
 */

 'lifetime' => env('SESSION_LIFETIME', 120),

 'expire_on_close' => false,

SessionTimeOut.php中间件

<?php

namespace App\Http\Middleware;

use Closure;
use App\Traits\CacheQueryResults;

class SessionTimeOut
{
    use CacheQueryResults;

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        // session()->forget('lastActivityTime');

        if (! session()->has('lastActivityTime')) {
            session(['lastActivityTime' => now()]);
        }

        // dd(
        //     session('lastActivityTime')->format('Y-M-jS h:i:s A'),
        //     now()->diffInMinutes(session('lastActivityTime')),
        //     now()->diffInMinutes(session('lastActivityTime')) >= config('session.lifetime')
        // );

        if (now()->diffInMinutes(session('lastActivityTime')) >= (config('session.lifetime') - 1) ) {
            if (auth()->check() && auth()->id() > 1) {
               $user = auth()->user();
               auth()->logout();

               $user->update(['is_logged_in' => false]);
               $this->reCacheAllUsersData();

               session()->forget('lastActivityTime');

               return redirect(route('users.login'));
           }

       }

       session(['lastActivityTime' => now()]);

       return $next($request);
    }
}

Kernel.php

/**
 * The application's route middleware groups.
 *
 * @var array
 */
 protected $middlewareGroups = [
     'web' => [
         \App\Http\Middleware\EncryptCookies::class,
         \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
         \Illuminate\Session\Middleware\StartSession::class,
         // \Illuminate\Session\Middleware\AuthenticateSession::class,
         \Illuminate\View\Middleware\ShareErrorsFromSession::class,
         \App\Http\Middleware\VerifyCsrfToken::class,
         \Illuminate\Routing\Middleware\SubstituteBindings::class,
         \App\Http\Middleware\SessionTimeOut::class,
     ],
];

【问题讨论】:

  • 会话超时后屏幕上是否显示任何错误?
  • 不。没有错误,它只是注销但不对数据库执行任何数据库操作。
  • 在注销前执行数据库操作或尝试使用像 \Auth::guard('admin')->logout();return redirect()->route('admin.login');
  • 不。还是一样。
  • 您是否获得了更新的用户详细信息 dd($user);更新后?is_logged_in=false in db?

标签: php laravel authentication session laravel-5.6


【解决方案1】:

您正在比较与中间件中相同的会话生命周期。

这意味着当会话到期时,您的中间件将不会(永远)被调用。用户将移动到登录页面。

如果您想在数据库中保存条目,您可以设置长时间会话生存期,并在中间件中使用您自定义的时间来注销。

config/session.php 中的变化

'lifetime' => 525600, // for one year, it will be in minute, use as you want. 

中间件更改如下,两小时后退出。

   if (now()->diffInMinutes(session('lastActivityTime')) >= (120) ) {  // also you can this value in your config file and use here
       if (auth()->check() && auth()->id() > 1) {
           $user = auth()->user();
           auth()->logout();

           $user->update(['is_logged_in' => false]);
           $this->reCacheAllUsersData();

           session()->forget('lastActivityTime');

           return redirect(route('users.login'));
       }

   }

通过这种方式,您的会话不会自动过期,您可以操作数据。

【讨论】:

  • 您的解决方案有效,但前提是session('lastActivityTime') 有价值。当会话过期时,session('lastActivity') 会被 Laravel 自动更新并重定向到登录页面。在此之前,我想将is_logged_in 属性设置为false0,我该如何实现?
  • 这就是我想说的。如果会话自动过期,我们无法获取数据,因此解决方案是增加会话生命周期,在中间件中,使用自定义时间注销。检查更新的答案。
【解决方案2】:

注销前需要更新数据库。因为注销后无法执行$user-&gt;update()。所以请尝试以下方式:

if (auth()->check() && auth()->id() > 1) {
    $user = auth()->user();        

    $user->update(['is_logged_in' => false]);
    $this->reCacheAllUsersData();

    session()->forget('lastActivityTime');

    //Add Logout method here..
    auth()->logout();

    return redirect(route('users.login'));
}

【讨论】:

  • 不。它没有用。仅在应用您的解决方案后,is_logged_in 列才设置为 1
  • @SaiyanPrince 这意味着数据库已更新。现在的问题是你想在is_logged_in 列中保存什么?是true or false 还是0 or 1
  • 不。 1true 在用户登录时设置。我想在用户通过会话超时注销时将其设置为false0。我已经完成了手动过程。我现在正在寻找数据库表的自动更新。
【解决方案3】:

请在中间件中检查小于120,例如如果条件低于115或119,然后检查它

if (now()->diffInMinutes(session('lastActivityTime')) == config('session.lifetime')) {
....
}

【讨论】:

    猜你喜欢
    • 2018-12-25
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 2017-03-04
    • 2013-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多