Redis队列下Laravel Audit异步日志缺失:Task审计日志未生成
问题解决:Laravel Audit在Redis队列下不记录Task审计日志
核心原因
异步队列任务与原请求上下文完全隔离,Laravel Audit依赖的用户身份、请求IP、UA等信息在队列环境中丢失,导致审计事件无法触发或无法生成有效日志。
解决方案
1. 传递并恢复队列任务中的审计上下文
在触发队列任务时,将原请求的审计关键信息传递进去,在任务执行时恢复上下文:
- 触发任务时传递上下文(比如Booking创建事件中):
// 收集当前请求的审计上下文 $auditContext = [ 'user_id' => auth()->id(), 'ip_address' => request()->ip(), 'user_agent' => request()->userAgent(), 'url' => request()->fullUrl(), ]; // 携带上下文分发队列任务 ProcessCreateTask::dispatch($booking, $auditContext);
- 队列任务中恢复上下文:
use OwenIt\Auditing\Facades\Audit; use App\Models\User; class ProcessCreateTask implements ShouldQueue { public function handle($booking, $auditContext) { // 恢复用户身份 if ($userId = $auditContext['user_id']) { $user = User::find($userId); auth()->login($user); // 给自定义解析器设置上下文(如果用了自定义UserResolver) app()->instance('audit_user', $user); } // 手动设置审计的请求元数据 Audit::setIpAddress($auditContext['ip_address']); Audit::setUserAgent($auditContext['user_agent']); Audit::setUrl($auditContext['url']); // 创建Task记录 $task = Task::create([ 'booking_id' => $booking->id, // 其他Task字段 ]); // 可选:手动触发审计(确保事件未遗漏) $task->audit(); } }
2. 调整自定义UserResolver适配队列环境
如果使用了自定义的UserResolver,需要修改它支持从上下文获取用户,而非仅依赖请求的Auth状态:
use OwenIt\Auditing\Contracts\UserResolver; class UserResolver implements UserResolver { public static function resolve() { // 优先从应用上下文获取队列传递的用户 if (app()->has('audit_user')) { return app('audit_user'); } // 原有的Web/API请求Auth逻辑 foreach (config('audit.user.guards') as $guard) { if (auth()->guard($guard)->check()) { return auth()->guard($guard)->user(); } } return null; } }
3. 确保队列Worker加载最新配置
重启队列Worker,避免缓存的旧配置导致审计逻辑失效:
php artisan queue:restart
同时确认队列环境的AUDITING_ENABLED环境变量为true,确保审计功能在队列中启用。
4. 强制触发Task审计(兜底方案)
如果以上方法仍未生效,可在Task创建后手动调用审计方法,强制生成审计日志:
$task = Task::create([...]); // 手动触发创建事件的审计 $task->auditEvent('created');
内容的提问来源于stack exchange,提问作者M a m a D
相关产品推荐
相关产品推荐

