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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 16:43:12