You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel删除用户后多端会话重复检索已删除用户的解决方法

Laravel删除账号后其他端重复查询已删除用户的解决方法

Laravel默认的SessionGuard仅会缓存查询到的有效用户实例,当账号被删除后,user()方法每次调用都无法查到有效用户,也不会标记用户已不存在的状态,因此会重复执行数据库查询。

方案一:自定义Guard解决单次请求重复查询问题

通过重写SessionGuard的user()方法,增加用户不存在的标记,同时触发登出逻辑清空无效认证信息:

  • 第一步:创建自定义Guard类
// 路径 app/Guards/SessionGuard.php
<?php

namespace App\Guards;

use Illuminate\Auth\SessionGuard as BaseSessionGuard;

class SessionGuard extends BaseSessionGuard
{
    // 标记用户不存在,避免重复查询
    protected $userNotFound = false;

    public function user()
    {
        // 已登出或已确认用户不存在,直接返回null
        if ($this->loggedOut || $this->userNotFound) {
            return null;
        }

        // 已有用户缓存直接返回
        if (!is_null($this->user)) {
            return $this->user;
        }

        $id = $this->session->get($this->getName());

        // 尝试从会话获取用户
        if (!is_null($id) && $this->user = $this->provider->retrieveById($id)) {
            $this->fireAuthenticatedEvent($this->user);
        }

        // 会话没查到,尝试从记住我cookie获取
        if (is_null($this->user) && !is_null($recaller = $this->recaller())) {
            $this->user = $this->userFromRecaller($recaller);

            if ($this->user) {
                $this->updateSession($this->user->getAuthIdentifier());
                $this->fireLoginEvent($this->user, true);
            }
        }

        // 确认用户不存在,打标记并执行登出清空无效信息
        if (is_null($this->user)) {
            $this->userNotFound = true;
            $this->logout();
        }

        return $this->user;
    }
}
  • 第二步:注册自定义Guard驱动
    在app/Providers/AuthServiceProvider.php的boot方法中添加驱动注册逻辑:
public function boot()
{
    $this->registerPolicies();

    \Auth::extend('custom_session', function ($app, $name, array $config) {
        $guard = new \App\Guards\SessionGuard(
            $name,
            $app['auth']->createUserProvider($config['provider']),
            $app['session.store'],
            $app['request']
        );

        if (method_exists($guard, 'setCookieJar')) {
            $guard->setCookieJar($app['cookie']);
        }
        if (method_exists($guard, 'setDispatcher')) {
            $guard->setDispatcher($app['events']);
        }
        if (method_exists($guard, 'setRequest')) {
            $guard->setRequest($app->refresh('request', $guard, 'setRequest'));
        }

        return $guard;
    });
}
  • 第三步:修改认证配置使用自定义Guard
    修改config/auth.php中的guards配置:
'guards' => [
    'web' => [
        'driver' => 'custom_session',
        'provider' => 'users',
    ],
],

修改完成后,单次请求内首次查询到用户不存在就会打标记,后续调用auth()相关方法不会再重复查询,同时会自动清空当前会话和记住我cookie,用户后续访问不会再携带无效认证信息。

方案二:主动清理所有端会话

如果需要删除账号后立刻让所有端的会话失效,不需要等用户访问触发,可以选择以下方式:

  • 若使用数据库存储会话:删除sessions表中所有user_id为当前删除用户ID的记录即可
  • 若使用Redis/文件存储会话:可以给用户表增加session_version字段,登录时将版本号存入会话,每次认证时比对用户表的版本号和会话存储的版本号,删除用户时将版本号+1,所有旧会话就会自动失效
  • 也可以遍历对应存储的所有会话,匹配对应用户ID后批量删除,适合会话量不大的场景

内容的提问来源于stack exchange,提问作者Tung Hoang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 14:27:05