Laravel 7能否无需将用户存入数据库实现登录?
解决Laravel 7中无需数据库存储实现用户登录的问题
首先得明确你当前代码中Auth::login($user)没生效的核心原因:当调用这个方法时,Laravel会把用户的ID存入会话,但后续请求会尝试通过默认的EloquentUserProvider从数据库中查找该ID对应的用户。而第三类用户并没有被保存到数据库,所以后续请求会验证失败,看起来就像“登录没生效”。
下面给出两种可行的解决方案,推荐使用第一种规范的自定义Provider方案:
方案一:自定义API驱动的UserProvider(推荐)
这种方式符合Laravel的认证架构规范,后续维护和扩展更方便。
1. 创建自定义UserProvider类
在app/Auth/ApiUserProvider.php新建文件,实现Laravel的用户提供者接口:
<?php namespace App\Auth; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Auth\Authenticatable as UserContract; use App\User; class ApiUserProvider implements UserProvider { protected $apiUrl; protected $cookieName; public function __construct($apiUrl, $cookieName) { $this->apiUrl = $apiUrl; $this->cookieName = $cookieName; } // 根据用户唯一标识(这里用vid)获取用户 public function retrieveById($identifier) { $userArray = json_decode(file_get_contents($this->apiUrl . '?type=json&vid=' . $identifier)); if (!$userArray->result) { return null; } $user = new User(); $user->vid = $userArray->vid; $user->name = $userArray->firstname; $user->surname = $userArray->lastname; $user->division = $userArray->division; $user->setAuthIdentifier($userArray->vid); // 设置Laravel认证所需的唯一标识 return $user; } // 第三类用户不需要记住登录功能,直接返回null public function retrieveByToken($identifier, $token) { return null; } // 空实现,无需保存记住令牌到数据库 public function updateRememberToken(UserContract $user, $token) { // 无需操作 } // 登录时我们已通过API验证凭证,这里留空即可 public function retrieveByCredentials(array $credentials) { return null; } // 验证凭证,这里直接返回true(因为已经通过API验证过) public function validateCredentials(UserContract $user, array $credentials) { return true; } }
2. 注册自定义Provider
在app/Providers/AuthServiceProvider.php的boot方法中注册这个提供者:
use App\Auth\ApiUserProvider; use Illuminate\Support\Facades\Auth; public function boot() { $this->registerPolicies(); // 注册自定义API用户提供者 Auth::provider('api', function ($app, array $config) { return new ApiUserProvider($config['api_url'], $config['cookie_name']); }); }
3. 配置Auth Guard
修改config/auth.php,添加一个专门用于第三类用户的Guard和Provider:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', // 原有的Eloquent提供者,用于前两类已注册用户 ], 'api_guest' => [ 'driver' => 'session', 'provider' => 'api_guests', // 自定义的API提供者,用于第三类用户 ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\User::class, ], 'api_guests' => [ 'driver' => 'api', // 对应我们注册的provider名称 'api_url' => env('API_AUTH_URL'), // 在.env中配置你的API地址 'cookie_name' => env('API_COOKIE_NAME'), // 配置API验证用的cookie名称 ], ],
4. 修改LoginController的登录逻辑
在处理第三类用户时,使用自定义的Guard完成登录:
// ... 原有代码 ... else { $user = new User(); $user->division = $user_array->division; $user->vid = $user_array->vid; $user->name = $user_array->firstname; $user->surname = $user_array->lastname; $user->setAuthIdentifier($user_array->vid); // 使用自定义的api_guest Guard登录 Auth::guard('api_guest')->login($user); return redirect('/'); }
5. 配置路由中间件
如果你的路由需要验证第三类用户,指定使用api_guest Guard:
// 第三类用户可访问的路由 Route::middleware('auth:api_guest')->group(function () { Route::get('/', 'HomeController@index'); // 其他路由... }); // 前两类已注册用户的路由,继续使用原有的web Guard Route::middleware('auth')->group(function () { Route::get('/admin', 'AdminController@index'); // 其他路由... });
方案二:临时会话存储用户信息(快速实现)
如果不想自定义Provider,可以通过会话存储用户信息,再用中间件自动加载:
1. 修改LoginController的登录逻辑
// ... 原有代码 ... else { $tempUser = [ 'vid' => $user_array->vid, 'name' => $user_array->firstname, 'surname' => $user_array->lastname, 'division' => $user_array->division, ]; // 将用户数据存入会话 session(['temp_user' => $tempUser]); // 手动触发登录状态 Auth::loginUsingId($user_array->vid, false); return redirect('/'); }
2. 创建加载临时用户的中间件
执行命令生成中间件:php artisan make:middleware LoadTempUser
修改app/Http/Middleware/LoadTempUser.php:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; use App\User; class LoadTempUser { public function handle($request, Closure $next) { // 未认证但会话有临时用户数据时,加载用户 if (!Auth::check() && $request->session()->has('temp_user')) { $userData = $request->session()->get('temp_user'); $user = new User(); $user->vid = $userData['vid']; $user->name = $userData['name']; $user->surname = $userData['surname']; $user->division = $userData['division']; $user->setAuthIdentifier($userData['vid']); Auth::setUser($user); } return $next($request); } }
3. 注册中间件
在app/Http/Kernel.php的web中间件组中添加这个中间件:
protected $middlewareGroups = [ 'web' => [ // ... 其他中间件 ... \App\Http\Middleware\LoadTempUser::class, ], ];
这种方式的缺点是用户信息存在会话中,API用户信息更新时不会同步,适合快速验证需求。
内容的提问来源于stack exchange,提问作者Emilio
相关产品推荐
相关产品推荐

