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

Laravel 5用户访问信息记录重复保存问题求助

解决Laravel中间件重复记录访问日志的问题

你遇到的重复记录问题,本质是中间件会拦截每一次HTTP请求(包括页面刷新、AJAX请求甚至静态资源加载),所以当前逻辑会触发多次保存操作。下面给你两个实用的解决方案,按需选择:

方案一:会话级单次记录(推荐)

利用Laravel的Session标记当前会话是否已记录过访问日志,同一个浏览器会话内只会记录首次访问:

public function handle($request, Closure $next) {
    // 先做登录校验
    if(!Auth::guard('web_admin')->check()){
        return redirect('admin/login');
    }

    $user = Auth::guard('web_admin')->user();
    // 检查Session是否已有记录标记
    if (!$request->session()->has('admin_access_logged')) {
        // 执行你的日志保存逻辑
        $log = new AccessLog(); // 替换成你的日志模型
        $log->user_id = $user->id;
        $log->ip = $request->ip();
        $log->os = $this->getOs($request->header('User-Agent')); // 你的操作系统识别方法
        $log->browser = $this->getBrowser($request->header('User-Agent')); // 你的浏览器识别方法
        $log->timestamp = now();
        $log->save();

        // 写入Session标记,避免重复记录
        $request->session()->put('admin_access_logged', true);
    }

    return $next($request);
}

说明:

  • 同一个用户打开浏览器访问后台,只会在第一次进入时记录,后续刷新、跳转页面都不会重复写入。
  • 用户关闭浏览器后Session失效,下次打开会重新记录新的访问。

方案二:时间周期内单次记录

如果需要同一用户在指定时间(比如1小时)内不管访问多少次只记录一次,可以通过数据库查询判断:

public function handle($request, Closure $next) {
    if(!Auth::guard('web_admin')->check()){
        return redirect('admin/login');
    }

    $user = Auth::guard('web_admin')->user();
    $currentIp = $request->ip();
    // 检查最近1小时内是否已有该用户+IP的访问记录
    $hasRecentLog = AccessLog::where('user_id', $user->id)
        ->where('ip', $currentIp)
        ->where('timestamp', '>=', now()->subHour())
        ->exists();

    if (!$hasRecentLog) {
        // 执行日志保存逻辑(和方案一一致)
        $log = new AccessLog();
        $log->user_id = $user->id;
        $log->ip = $currentIp;
        $log->os = $this->getOs($request->header('User-Agent'));
        $log->browser = $this->getBrowser($request->header('User-Agent'));
        $log->timestamp = now();
        $log->save();
    }

    return $next($request);
}

说明:

  • 可以根据业务需求调整时间间隔,比如把subHour()改成subDay()就是一天内只记录一次。
  • 若用户更换IP访问,即使在时间周期内也会重新记录,适合需要区分IP的场景。

额外优化:排除静态资源请求

如果你的中间件是全局应用,建议排除CSS、JS、图片等静态资源请求,避免不必要的判断:

// 放在登录校验之前,排除静态资源路径
$exceptPaths = ['/css/', '/js/', '/images/', '/fonts/'];
foreach ($exceptPaths as $path) {
    if (str_starts_with($request->path(), $path)) {
        return $next($request);
    }
}

内容的提问来源于stack exchange,提问作者Jorge Omar Tovar Martínez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:22:55