Laravel 5自定义Auth登录:支持userName或loginName登录
嘿,这个需求其实挺常见的,我给你两种靠谱的实现方案,你可以根据项目的实际情况来选择:
方案1:直接查询验证(快速上手)
这种方式不需要改动Laravel的默认认证体系,直接手动查询用户再验证密码,逻辑清晰好理解:
// 获取用户输入的登录标识(可能是userName或loginName) $loginIdentifier = $request->userName; $password = $request->passHash; // 查找匹配的用户:要么userName匹配,要么loginName匹配且loginName不为空 $user = \App\Models\User::where('userName', $loginIdentifier) ->orWhere(function ($query) use ($loginIdentifier) { $query->where('loginName', $loginIdentifier) ->whereNotNull('loginName'); }) ->first(); // 验证用户是否存在且密码正确 if ($user && \Illuminate\Support\Facades\Hash::check($password, $user->password)) { // 手动登录用户 \Illuminate\Support\Facades\Auth::login($user); // 这里写登录成功后的逻辑,比如跳转仪表盘 return redirect()->intended('/dashboard'); } else { // 认证失败,返回错误提示 return back()->withErrors(['userName' => '用户名或密码错误']); }
注意:一定要加上whereNotNull('loginName')这个条件,避免匹配到那些还没设置loginName的用户(他们的loginName字段是NULL),防止出现不必要的匹配冲突。
方案2:自定义认证逻辑(优雅适配Laravel体系)
如果你希望继续使用Auth::attempt()的写法,保持代码风格一致,可以自定义用户认证的查询逻辑。这里提供两种实现方式:
方式A:在User模型中添加范围查询
在你的User模型里定义一个范围查询方法,封装匹配逻辑,让代码更简洁:
// 在User模型中添加范围查询 public function scopeByLoginIdentifier($query, $identifier) { return $query->where('userName', $identifier) ->orWhere(function ($q) use ($identifier) { $q->where('loginName', $identifier) ->whereNotNull('loginName'); }); } // 然后在认证代码里调用: $user = \App\Models\User::byLoginIdentifier($request->userName)->first(); if ($user && \Illuminate\Support\Facades\Hash::check($request->passHash, $user->password)) { \Illuminate\Support\Facades\Auth::login($user); // ... 后续登录成功逻辑 }
方式B:扩展EloquentUserProvider(完全适配Auth::attempt)
如果你想完全沿用Auth::attempt()的写法,不改动原有调用逻辑,可以扩展Laravel默认的用户提供者:
- 创建自定义用户提供者类:
namespace App\Providers; use Illuminate\Auth\EloquentUserProvider; use Illuminate\Contracts\Auth\Authenticatable as UserContract; class CustomUserProvider extends EloquentUserProvider { public function retrieveByCredentials(array $credentials) { if (empty($credentials) || (count($credentials) === 1 && array_key_exists('password', $credentials))) { return; } // 获取登录标识 $loginIdentifier = $credentials['userName']; unset($credentials['password']); // 构建匹配查询 $query = $this->createModel()->newQuery(); return $query->where('userName', $loginIdentifier) ->orWhere(function ($q) use ($loginIdentifier) { $q->where('loginName', $loginIdentifier) ->whereNotNull('loginName'); }) ->first(); } }
- 在
AuthServiceProvider的boot方法中注册这个提供者:
public function boot() { $this->registerPolicies(); \Illuminate\Support\Facades\Auth::provider('custom', function ($app, array $config) { return new CustomUserProvider($app['hash'], $config['model']); }); }
- 修改
config/auth.php中的用户提供者配置:
'providers' => [ 'users' => [ 'driver' => 'custom', // 替换为自定义的驱动名 'model' => App\Models\User::class, ], ],
完成后,你就可以继续使用原来的Auth::attempt()代码了,它会自动用我们的自定义逻辑查找用户:
if (Auth::attempt(['userName' => $request->userName, 'password' => $request->passHash])) { // 登录成功后的逻辑 }
两种方案各有优劣:方案1快速简单,适合小项目或临时需求;方案2更符合Laravel的设计规范,适合需要长期维护的大型项目。你可以根据自己的情况选择~
内容的提问来源于stack exchange,提问作者Nicholas Déziel
相关产品推荐
相关产品推荐

