Laravel 6多Auth Guard登录与路由异常问题求助
首先,咱们先拆解你遇到的两个核心问题:
1. 公共头部模板调用 auth()->user() 报错的原因
auth()->user() 默认会使用 web 守卫去获取用户,但你登录的是 student 守卫——这两个守卫对应的是完全独立的用户表和认证会话,所以当你用学生身份登录后,web 守卫下并没有认证用户,自然会抛出「Trying to get property of non-object」的错误。
解决方法:全局获取当前登录用户(兼容多守卫)
你需要在视图里检查所有可能的认证守卫,拿到当前实际登录的用户。这里有两种优雅的实现方式:
方式一:直接在视图中判断
在你的公共头部模板里替换原有的 auth()->user() 逻辑:
@php // 依次检查web、student守卫,拿到第一个已认证的用户 $currentUser = auth()->guard('web')->user() ?? auth()->guard('student')->user() ?? null; @endphp @if($currentUser) <span>欢迎,{{ $currentUser->name }}</span> <a href="{{ route('logout') }}">退出登录</a> @else <a href="{{ route('login') }}">普通用户登录</a> <a href="{{ route('studentlogin') }}">学生登录</a> @endif
方式二:全局共享用户变量(更优雅)
在 app/Providers/AppServiceProvider.php 的 boot 方法中添加视图共享逻辑,这样所有视图都能直接使用 $currentUser:
public function boot() { view()->composer('*', function ($view) { $view->with('currentUser', auth()->guard('web')->user() ?? auth()->guard('student')->user() ?? null ); }); }
之后在头部模板里直接用 $currentUser 即可,不用再重复写判断逻辑。
2. 多守卫中间件同时使用失效的问题
你不能把 auth 和 auth:student 放进同一个中间件数组里——Laravel 的 auth 中间件要求用户必须同时通过所有指定守卫的认证,而一个用户不可能既是普通用户(web守卫)又是学生(student守卫),所以这种写法会直接拦截所有请求,导致没有用户被认证。
解决方法:按路由需求拆分中间件
- 普通用户专属路由组:保持
middleware:auth(对应web守卫) - 学生专属路由组:保持
middleware:auth:student(对应student守卫) - 如果有需要任意已认证用户都能访问的路由,自定义一个中间件来实现:
步骤1:创建自定义中间件
运行命令生成中间件:
php artisan make:middleware EnsureAnyAuthenticated
步骤2:编写中间件逻辑
打开 app/Http/Middleware/EnsureAnyAuthenticated.php,替换为以下代码:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class EnsureAnyAuthenticated { public function handle($request, Closure $next) { // 只要web或student守卫有一个通过认证,就允许访问 if (Auth::guard('web')->check() || Auth::guard('student')->check()) { return $next($request); } // 未认证则跳转到登录页 return redirect()->route('login'); } }
步骤3:注册中间件
在 app/Http/Kernel.php 的 $routeMiddleware 数组里添加注册项:
protected $routeMiddleware = [ // ... 其他已有的中间件 'auth.any' => \App\Http\Middleware\EnsureAnyAuthenticated::class, ];
之后,需要开放给所有已认证用户的路由组,就可以使用 middleware:auth.any 了。
额外的两处小问题修复
LoginController构造函数的错误中间件
你的构造函数里加了$this->middleware('student')->except('destroy');,这会导致未登录的用户无法访问登录页面(因为student中间件要求必须是已认证的学生),直接删掉这行即可:public function __construct() { $this->middleware('guest')->except('destroy'); // 删掉下面这行 // $this->middleware('student')->except('destroy'); }重复的登录路由
你现在的两个登录路由指向同一个create方法:Route::get('/login', 'LoginController@create')->name('login'); Route::get('/login/student', 'LoginController@create')->name('studentlogin');建议拆分出两个方法,比如
showUserLoginForm和showStudentLoginForm,分别返回不同的登录视图,避免视图混淆。
内容的提问来源于stack exchange,提问作者dbp

