【问题标题】:Force logout of all users in LaravelLaravel 强制注销所有用户
【发布时间】:2019-04-30 20:21:13
【问题描述】:

如何强制所有用户在 SPA 中退出?我希望这样当我部署新版本时,所有用户都会自动退出。

我尝试了以下方法,但我不确定这是否是最安全的方法。

php artisan key:generate

【问题讨论】:

  • 刷新所有会话。 不要使用key:generate,因为它会使您生成的任何加密数据无效并且您将无法恢复它们
  • 如果需要,您的应用程序设计首先确实有问题。

标签: php laravel laravel-5 vue.js laravel-artisan


【解决方案1】:

如果您的会话数据存储在数据库中,则需要清除sessions 表。运行一个简单的 SQL 查询即可解决问题:

DELETE FROM sessions;

如果您的会话存储在文件中,那么正如@Karl 建议的那样,您需要从文件系统中删除会话文件:

rm -rf storage/framework/sessions/*

还可以更改会话 cookie 的名称以强制所有会话无效,但这是更改代码而不是清除数据。该名称可以在config/session.php 文件中的cookie 键中更新。不推荐使用此选项。

【讨论】:

    【解决方案2】:

    如您所见,SessionGuard 做了一些事情,它们与您在环境中设置的SESSION_DRIVER 类型无关。

    因此,在阅读了 Taylor 和其他一些 Laravel 重量级人物在论坛上关于为什么没有这么简单的功能的讨论之后,也许最好的解决方案是创建一个部署后 JobCommand你可以运行它会简单地循环遍历所有用户,所以无论 Session 是什么设置。我会尝试类似:

    \App\User::each(function ($u) {
        Auth::login($u);
        Auth::logout();
    });
    

    【讨论】:

      【解决方案3】:

      您可以销毁所有会话。如果您使用 Laravel Envoy 来处理部署,您可以添加以下行。

      rm -rf storage/framework/sessions/*
      

      如果您使用数据库会话驱动程序,清除会话表很容易。

      DB::table('sessions')->truncate();
      

      【讨论】:

      • 会话表不存在
      • 您似乎发布了敏感/私人信息。如果是这种情况,请重置您的密码和/或撤销 API 密钥和令牌,因为它们在互联网上发布时被视为已泄露。
      【解决方案4】:

      这真的取决于您选择的会话驱动器。

      • 如果您使用文件驱动器,您可以删除存储/框架/会话 路径
      • 如果您使用数据库驱动器,您可以删除所有会话行 表,

      对于任何其他驱动器,您都可以像其他驱动器一样做到这一点。

      你也可以在app/session.php中修改cookie值,这样用户会因为cookie与配置不匹配而自动退出

      值得注意的是,Laravel 实际上只将活动会话存储在 会话文件夹;那些被“记住”但没有被记住的人 主动访问您的应用程序不计入这些会话。 因此,仅删除文件不会完成工作。

      您还必须清除用户表中的所有记住令牌,因为这 token 与 cookie 中存储的本地 token 结合使用 当用户重新连接时重新创建会话。

      【讨论】:

        【解决方案5】:

        如果使用的驱动程序是文件,我想分享另一种实现此目的的方法。

        这是“纯”的 php 方式,所以它可以是一个 helper 'flush_sessions()':

        $sessions = glob(storage_path("framework/sessions/*"));
        foreach($sessions as $file){
          if(is_file($file))
            unlink($file);
        }
        

        使用这个功能安全吗? PHP 会将隐藏文件保存在给定目录(.gitignore)中...所以,试试看,它是安全的。

        值得一提的是,如果你把它放在一个控制器方法中,那么 你的会话 将在删除文件后恢复(显然,Laravel 会在请求结束后尝试更新文件并且如果它不存在,将重新创建它)。但是所有其他会话(用户)都将被注销。例如,如果您在 php artisan tinker 中运行此代码,将不会保留您自己的会话文件(因为 artisan 使用 'array' 驱动程序运行)。

        但是,我认为这很有用。例如:如果管理员用户想要注销除他自己以外的所有用户。

        例如: 您有两个会话:

        运行函数后,你只有一个(使用它的用户):

        我希望这对某人有所帮助。

        【讨论】:

          【解决方案6】:

          //注销特定用户:

          //$id == user id to to whom you want to logout
          \DB::table('users')->where('id', $id)->update(['remember_token' => null]);
          \DB::table('sessions')->where('user_id', $id)->delete();
          

          //注销所有用户

          $sessions = glob(storage_path("framework/sessions/*"));
          foreach ($sessions as $file) {
          if (is_file($file))
          unlink($file);
          }
          //$id == user id to to whom you want to logout
          \DB::table('users')->update(['remember_token' => null]);
          \DB::table('sessions')->truncate();
          

          如果您不使用数据库作为会话驱动程序,则无需使用会话表操作。

          【讨论】:

            【解决方案7】:

            我将所有用户的记忆令牌更新为空白,然后刷新存储的会话,然后修改 HomeController。

                 \DB::table('users')->update(array(
                'remember_token' => '',
                'logout_at' => Carbon::now()->toDateTimeString()));
                Session::flush();
            

            然后在 HomeController 中修改索引函数

                public function index()
            {
                if (Auth::check()) {
                    $token = Auth::user()->remember_token;
                    if ($token) {
                        return view('home');
                    } else {
                        return redirect('/logout');
                    }
                } else {
                    return view('home');
                }
                
            }
            

            【讨论】: