Laravel8集成LDAPRecord认证后Auth::user()跨请求返回null
问题原因
你遇到的登录态无法跨请求持久化问题,由3个核心错误导致:
- 错误使用
shouldUse()方法做动态guard切换:shouldUse()仅会修改当前请求生命周期内的默认guard,不会将当前认证使用的guard标识持久化到session。两个自定义guardpio和voj的session认证存储键是互相隔离的,如果你通过vojguard认证成功,下一个请求Laravel会默认加载配置文件中写死的pioguard读取认证数据,自然无法获取登录态;即使是pioguard登录的场景,缺少LDAP唯一标识同步也会导致认证失效。 - 未配置LDAP唯一标识(GUID)同步:LDAP Record的数据库认证驱动要求必须在本地
users表存储AD用户的唯一objectguid字段,作为本地数据库用户和LDAP用户的绑定依据。你当前的同步规则仅同步了邮箱、姓名字段,当前请求中因刚完成LDAP查询可以返回完整用户模型,但跨请求时guard从session取出本地用户ID后,无法通过GUID匹配到对应LDAP用户实例,会直接返回null。 - 认证逻辑存在细节缺陷:构造
voj域登录凭证时仍使用@pio.rs邮箱后缀,会导致所有voj域用户认证失败;remember参数的判断逻辑冗余,没有使用Laravel内置的参数取值方法。
修复步骤
新增本地用户表GUID字段
新建数据库迁移,为users表添加存储LDAP唯一标识的字段:Schema::table('users', function (Blueprint $table) { $table->string('guid', 64)->unique()->after('id'); });执行迁移
php artisan migrate完成字段添加。修改模型和认证提供者配置
首先在App\Models\User模型中添加属性,指定LDAP关联字段:protected $guidKey = 'guid';然后修改
config/auth.php中两个LDAP提供者的同步规则,加入GUID字段同步:'sync_attributes' => [ 'guid' => 'objectguid', // 新增AD唯一标识同步 'email' => 'mail', 'name' => 'cn', ],两个提供者的配置都需要加这一行。
修复登录控制器逻辑
调整登录认证代码,认证成功后将当前使用的guard标识存入session,同时修正voj域的邮箱后缀、简化remember参数取值:public function store(Request $request) { $remember = $request->boolean('remember'); // 尝试pio域认证 $pioCredentials = [ 'mail' => $request->input('username').'@pio.rs', 'password' => $request->input('password'), ]; auth()->shouldUse('pio'); if (auth()->attempt($pioCredentials, $remember)) { session(['auth_guard' => 'pio']); return redirect()->route('home'); } // 尝试voj域认证,替换为你voj域实际的邮箱后缀 $vojCredentials = [ 'mail' => $request->input('username').'@voj.rs', 'password' => $request->input('password'), ]; auth()->shouldUse('voj'); if (auth()->attempt($vojCredentials, $remember)) { session(['auth_guard' => 'voj']); return redirect()->route('home'); } return back()->withErrors(['username' => '账号或密码错误']); }记得把
@voj.rs替换成你vojAD域实际使用的邮箱后缀。添加全局guard判断逻辑
打开app/Http/Kernel.php,在web中间件组的StartSession中间件之后添加一段闭包中间件,保证每个请求启动时自动加载session中存储的guard标识:protected $middlewareGroups = [ 'web' => [ // 原有其他中间件保持不变 \Illuminate\Session\Middleware\StartSession::class, // 新增以下代码 function ($request, $next) { if (session()->has('auth_guard')) { auth()->shouldUse(session('auth_guard')); } return $next($request); }, // 原有其他中间件保持不变 ], ];补充登出逻辑
在登出方法中清除session中存储的guard标识,避免后续登录逻辑异常:public function logout() { auth()->logout(); session()->forget('auth_guard'); return redirect()->route('login'); }
验证操作
完成所有修改后,依次执行以下命令清除缓存:
php artisan config:clear php artisan route:clear php artisan cache:clear
清除浏览器本地存储的所有站点Cookie后重新登录,即可正常跨请求保持登录状态。
内容的提问来源于stack exchange,提问作者n_ivkovic021
相关产品推荐
相关产品推荐

