Laravel 8未加auth:sanctum中间件时Auth facade失效解决方案
Laravel 8 单路由适配多角色API权限实现方案
问题核心原因
出现你描述的问题,本质是两个点:
- 默认的
auth:sanctum中间件属于强制认证中间件,只要请求没携带有效登录凭证,会直接返回401未授权,根本不会走到控制器逻辑,所以访客拿不到任何内容 - 不挂载
auth:sanctum中间件时,Sanctum的认证守卫不会被加载,Auth::check()永远返回false,自然识别不到已登录用户的身份
另外你的原有代码还有两个明显问题:
- 存在语法笔误:
Events:all()缺少一个冒号,正确写法是Events::all() - 性能问题:先调用
->all()查询全表数据,再在内存中做where过滤,数据量稍大就会出现响应慢、内存占用高的问题
具体实现方案
不需要拆分多个路由,单路由即可适配访客、普通用户、管理员三类身份的返回逻辑,步骤如下:
1. 调整路由配置
路由不需要挂载强制认证的auth:sanctum中间件,正常写在公共路由组即可:
// routes/api.php Route::get('view', [ViewController::class, 'show']);
2. 重写控制器show方法
在方法开头手动指定使用Sanctum守卫识别身份,这个操作不会拦截未登录请求,同时能正确解析请求携带的有效token,再根据用户身份拼接查询条件,直接在数据库层完成过滤:
<?php namespace App\Http\Controllers; use App\Models\Events; use Illuminate\Support\Facades\Auth; class ViewController extends Controller { public function show() { // 指定当前请求使用sanctum守卫识别身份,不强制要求登录 Auth::shouldUse('sanctum'); // 初始化查询构造器 $eventsQuery = Events::query(); // 未登录用户、is_verified=0的普通用户,仅能查看已审核内容 if (!Auth::check() || Auth::user()->is_verified !== 1) { $eventsQuery->where('is_verified', 1); } // 按需添加排序、分页逻辑,这里示例按创建时间倒序 $eventsList = $eventsQuery->latest()->get(); // 标准JSON响应返回,不要直接echo输出 return response()->json($eventsList); } }
测试说明
在Hoppscotch等接口测试工具中测试时:
- 访客身份直接发起GET请求,不需要携带任何认证信息,会返回所有
is_verified=1的已审核内容 - 普通用户(
is_verified=0)登录后,在请求头携带Authorization: Bearer {用户token},接口会识别身份,同样返回所有已审核内容 - 管理员(
is_verified=1)登录后携带对应token请求,会返回全部文章内容
优化建议
- 不要在控制器中直接用
echo输出数据,使用Laravel自带的response()->json()返回,会自动处理Content-Type头、数据格式转换,避免出现跨域、格式解析错误 - 数据量较大时,建议把
->get()替换为->paginate()分页查询,避免单次查询数据过多导致接口超时 - 如果后续权限逻辑变复杂,可以把权限判断抽成中间件或者模型查询范围,减少控制器里的冗余逻辑
内容的提问来源于stack exchange,提问作者throwawaydev
相关产品推荐
相关产品推荐

