You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 了。


额外的两处小问题修复

  1. LoginController构造函数的错误中间件
    你的构造函数里加了 $this->middleware('student')->except('destroy');,这会导致未登录的用户无法访问登录页面(因为student中间件要求必须是已认证的学生),直接删掉这行即可:

    public function __construct() {
        $this->middleware('guest')->except('destroy');
        // 删掉下面这行
        // $this->middleware('student')->except('destroy');
    }
    
  2. 重复的登录路由
    你现在的两个登录路由指向同一个 create 方法:

    Route::get('/login', 'LoginController@create')->name('login');
    Route::get('/login/student', 'LoginController@create')->name('studentlogin');
    

    建议拆分出两个方法,比如 showUserLoginForm 和 showStudentLoginForm,分别返回不同的登录视图,避免视图混淆。

内容的提问来源于stack exchange,提问作者dbp

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:09:06