Laravel Sanctum API认证用户为null导致500错误,交易及登出接口无法正常调用问题
别着急,我之前也碰到过类似的问题,大概率是配置或者模型的几个小细节没做好,咱们一步步来排查:
首先,一定要先看Laravel的日志文件,路径是storage/logs/laravel.log,500错误肯定会在这里留下具体的报错信息——比如是不是某个guard没配置、模型少了必要的trait,这比瞎猜高效太多了。
接下来按这几个方向检查:
1. 确认Karyawan模型是否引入了Sanctum必需的Trait
Sanctum依赖HasApiTokens trait来处理token的生成和验证,你的Karyawan模型必须加上它:
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; use Laravel\Sanctum\HasApiTokens; // 必须引入这个 class Karyawan extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; // 加到这里 // 你的模型其他代码... }
如果没加这个,哪怕登录能返回token,后续验证时也会直接报错导致500。
2. 配置auth.php里的Guard和Provider
因为你用的是自定义的Karyawan模型,而不是默认的User模型,所以必须在config/auth.php里配置对应的guard和provider:
首先在guards数组里,给sanctum指定正确的provider:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'sanctum' => [ 'driver' => 'sanctum', 'provider' => 'karyawans', // 这里要指向你的karyawan provider ], ],
然后在providers数组里注册karyawan的provider:
'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, ], 'karyawans' => [ // 新增这个 'driver' => 'eloquent', 'model' => App\Models\Karyawan::class, ], ],
如果这里配置错了,Sanctum会默认去查User模型,自然找不到你的Karyawan用户,导致Auth::user()返回null,甚至直接抛出500错误。
3. 登录接口要使用正确的Guard验证并生成Token
你的登录接口必须指定用karyawans guard来验证用户,而不是默认的web或user guard,否则生成的token和后续认证不匹配:
比如AuthController的login方法应该这样写:
public function login(Request $request) { $credentials = $request->validate([ // 这里换成你实际的登录字段,比如username/email 'email' => 'required|email', 'password' => 'required', ]); // 用karyawans guard验证 credentials if (!Auth::guard('karyawans')->attempt($credentials)) { return response()->json(['message' => '登录凭证无效'], 401); } // 获取当前登录的karyawan用户 $user = Auth::guard('karyawans')->user(); // 生成sanctum token $token = $user->createToken('auth_token')->plainTextToken; return response()->json([ 'user' => $user, 'token' => $token, 'token_type' => 'Bearer', ]); }
4. 登出和交易接口里指定Guard获取用户
在TransaksiController和AuthController的logout方法里,最好明确指定用sanctum guard来获取用户,避免默认guard的问题:
比如TransaksiController的store方法:
public function store(Request $request) { // 用sanctum guard获取用户 $user = Auth::guard('sanctum')->user(); if (!$user) { return response()->json([ 'message' => 'Unauthorized - Token tidak valid atau sudah expired', 'debug' => [ 'auth_guard' => config('auth.defaults.guard'), 'header_auth' => $request->header('Authorization'), 'user_check' => Auth::guard('sanctum')->check() ] ], 401); } // 后续的验证和存储逻辑,比如: $validated = $request->validate([ // 你的交易字段验证规则 'amount' => 'required|numeric', // ...其他字段 ]); // 自动加入id_karyawan $validated['id_karyawan'] = $user->id; $transaksi = Transaksi::create($validated); return response()->json($transaksi, 201); }
登出接口的logout方法:
public function logout(Request $request) { // 用sanctum guard获取用户并删除当前token Auth::guard('sanctum')->user()->currentAccessToken()->delete(); // 如果要删除该用户所有token,可以改成: // Auth::guard('sanctum')->user()->tokens()->delete(); return response()->json(['message' => '登出成功']); }
最后检查Postman的请求头
确保你的请求头里Authorization字段是Bearer 你的token,注意Bearer后面有个空格,别漏了——有时候拼写错误或者空格缺失也会导致认证失败。
按照上面的步骤排查,应该就能解决Auth::user()为null和500错误的问题了。
内容来源于stack exchange

