Laravel中LDAP空密码用户能否无需密码调用logoutOtherDevices?
问题
我注意到Laravel的logoutOtherDevices方法会调用rehashUserPassword()方法,源码如下:
protected function rehashUserPassword($password, $attribute) { if (! Hash::check($password, $this->user()->{$attribute})) { throw new InvalidArgumentException('The given password does not match the current password.'); } return tap($this->user()->forceFill([ $attribute => Hash::make($password), ]))->save(); }
对于通过LDAP登录、数据库里存空密码的特定用户,能不能不用密码调用这个方法?目前我用硬编码的'password'调用Auth::logoutOtherDevices('password');能实现功能,但想找更优的无密码方案。
解决方案
针对LDAP登录且数据库密码为空的场景,给你两种靠谱的实现方式:
1. 自定义SessionGuard,跳过空密码校验
自己写一个继承原SessionGuard的Guard类,重写rehashUserPassword方法,对空密码用户跳过密码验证:
<?php namespace App\Auth; use Illuminate\Auth\SessionGuard as BaseSessionGuard; class SessionGuard extends BaseSessionGuard { protected function rehashUserPassword($password, $attribute) { $userPassword = $this->user()->{$attribute}; // 只有非空密码才校验,空密码直接跳过 if (!empty($userPassword) && !\Illuminate\Support\Facades\Hash::check($password, $userPassword)) { throw new \InvalidArgumentException('The given password does not match the current password.'); } // 空密码用户不需要重新哈希,直接返回用户模型 if (empty($userPassword)) { return $this->user(); } // 非空密码用户走原逻辑 return tap($this->user()->forceFill([ $attribute => \Illuminate\Support\Facades\Hash::make($password), ]))->save(); } }
然后在config/auth.php里配置使用这个自定义Guard:
'guards' => [ 'web' => [ 'driver' => 'custom_session', 'provider' => 'users', ], ],
最后在AuthServiceProvider的boot方法里注册这个自定义驱动:
use App\Auth\SessionGuard; use Illuminate\Support\Facades\Auth; public function boot() { Auth::extend('custom_session', function ($app, $name, array $config) { $guard = new SessionGuard($name, Auth::createUserProvider($config['provider']), $app['session.store']); 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; }); }
2. 直接实现登出核心逻辑,绕开原方法
logoutOtherDevices的本质是刷新用户密码哈希(让其他会话失效)+ 清除非当前会话。针对空密码用户,你可以直接写个自定义方法:
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; function logoutOtherDevicesWithoutPassword() { $user = Auth::user(); // 给空密码用户生成随机哈希值,让其他会话的密码校验失败 if (empty($user->password)) { $user->password = Hash::make(str()->random(60)); $user->save(); } // 调用原方法,此时密码已经更新,随便传个值都能过校验 Auth::guard()->logoutOtherDevices('any-string'); }
这个方法直接跳过了原方法的密码校验逻辑,用随机哈希值让其他会话失效,简单直接。
注意点
- 记得加判断,只对LDAP用户应用这个逻辑(比如给用户模型加个
is_ldap字段),别影响本地密码登录的用户。 - 自定义Guard的方式更规范,适合长期维护;直接写方法的方式更轻量,适合快速解决问题。
内容的提问来源于stack exchange,提问作者pileup
相关产品推荐
相关产品推荐

