Laravel 8+Sanctum中Auth::attempt与Hash::check验证失败问题
问题排查与解决方案
你的登录接口返回Unauthorized的核心原因是Laravel认证系统默认的字段名与你的数据库大写字段不匹配,以下是具体修复步骤:
1. 修复认证字段匹配问题
Laravel的Auth::attempt()默认会使用小写的username(或email)作为用户名字段,但你的数据库是大写的USERNAME,同时需要确保密码验证时能正确读取到PASSWORD字段。
方案一:修改User模型,明确指定认证字段
在User模型中添加以下方法,告诉Laravel认证时使用的用户名和密码字段:
//// protected $table = 'users'; protected $guarded = ['ID']; // 指定认证用的用户名字段 public function getAuthIdentifierName() { return 'USERNAME'; } // 指定认证用的密码字段(你已经写了这个,保留即可) public function getAuthPassword() { return $this->PASSWORD; } ////
方案二:在LoginController的login方法中明确指定认证字段
如果不想修改模型,也可以直接在构造认证凭据时使用数据库的大写字段名:
public function login(Request $request) { $data = $request->validate([ 'username' => 'required|string', 'password' => 'required|string' ]); // 构造匹配数据库字段的凭据 $credentials = [ 'USERNAME' => $data['username'], 'password' => $data['password'] ]; if(!Auth::attempt($credentials)) { return response()->json([ 'message' => 'Unauthorized' ], 401); } // 通过Auth获取用户,避免字段名匹配问题 $user = Auth::user(); $token = $user->createToken('apiToken')->plainTextToken; $res = [ 'user' => $user, 'token' => $token ]; return response($res, 201); }
2. 修复用户查询的字段名问题
原代码中User::where('username', $data['username'])->first()使用小写的username作为字段名,虽然MySQL默认不区分大小写,但为了严谨,建议改成与数据库一致的大写:
$user = User::where('USERNAME', $data['username'])->first();
验证修复效果
完成修改后,重新调用登录接口:
- 若使用方案一,原
Auth::attempt($credentials)可以保留,因为模型已经指定了正确的认证字段 - 若使用方案二,凭据已经匹配数据库字段,认证逻辑会正常执行
额外检查项
- 确认数据库中
PASSWORD字段存储的是哈希值(注册接口已经用Hash::make()处理,这部分没问题) - 确保请求时传递的
username和password参数正确,没有拼写错误
内容的提问来源于stack exchange,提问作者Hafid Maulana
相关产品推荐
相关产品推荐

