Laravel 9 API路由auth:api中间件跳转异常求助
问题描述
我安装了Laravel Breeze实现认证,登录注册表单可正常访问(http://localhost:8000/login)。但登录后访问受auth:api中间件保护的/api/categories路由时,会被重定向到首页;移除中间件后,路由可正常访问但无需登录验证。
可正常运行的路由代码
Route::controller(App\Http\Controllers\API\CategoryController::class)->group(function(){ Route::get('categories', 'index')->name('categories.index'); });
无法正常运行的路由代码
Route::group(['middleware' => 'auth:api'], function(){ Route::controller(App\Http\Controllers\API\CategoryController::class)->group(function(){ Route::get('categories', 'index')->name('categories.index'); }); });
CategoryController代码
<?php namespace App\Http\Controllers\API; use App\Http\Controllers\Controller; use Illuminate\Http\Request; use App\Models\Category; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Log; class CategoryController extends Controller { /** * Display a listing of the resource. * * @return \Illuminate\Http\Response */ public function index() { $cat = $this->getCategories(); return response()->json($cat); } /** * Show the form for creating a new resource. * * @return \Illuminate\Http\Response */ public function create() { $cat = $this->getCategories(); return view('create-category',compact('cat')); } /** * Store a newly created resource in storage. * * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { return Auth::user(); $category = Category::firstOrCreate( ['name' => $role_name], ['guard_name' => 'api'] ); } /** * Display the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function show($id) { $cat = $this->getCategories($id); // $cat = Category::where('id', $id)->get()->keyBy('id'); return response()->json($cat); } /** * Show the form for editing the specified resource. * * @param int $id * @return \Illuminate\Http\Response */ public function edit($id) { // } /** * Update the specified resource in storage. * * @param \Illuminate\Http\Request $request * @param int $id * @return \Illuminate\Http\Response */ public function update(Request $request, $id) { // } /** * Remove the specified resource from storage. * * @param int $id * @return \Illuminate\Http\Response */ public function destroy($id) { // } public function getParentCategory($id) { $cat = Category::where('id', $id)->get()->keyBy('id'); return $cat; } public function getChildCategory($id, $keyBy = null) { // return $keyBy; $cat = Category::where('parent_id', $id)->get()->keyBy('id'); return $cat; } private function setKeyBy($collection, $name) { $collection = $collection->keyBy($name); return $collection; } public function getCategories($category_id = null) { $cat = Category::where('id', '>', 0); if(!is_null($category_id)) { $cat = $cat->where('id', $category_id)->get()->keyBy('id'); } else { $cat = $cat->whereNull('parent_id')->get()->keyBy('id'); foreach($cat as $catID=>$catArray) { $subCat = $this->getChildCategory($catID, 'id'); // $subCat = $subCat->keyBy('id'); if ($subCat->first()) { $cat[$catID]['subcat'] = $subCat; } } } return $cat; } public function createCategoryForm() { $cat = $this->getCategories(); return view('create-category',compact('cat')); } public function categoryDropown($child_id = null) { $cat = $this->getCategories(); } public function categoryChildDropown($child_id) { $cat = Category::where('parent_id', $child_id)->get(); return $cat; } }
解决方案
问题核心是auth:api和Breeze默认的Web认证分属不同体系:Breeze用web guard基于会话认证,而auth:api默认用Token认证,两者状态不互通,所以Web登录后API guard仍识别不到用户。
方法一:改用auth:web中间件(适合前后端同构场景)
如果API是给项目内前端页面调用的,直接替换中间件,让Web会话的登录状态生效:
Route::group(['middleware' => 'auth:web'], function(){ Route::controller(App\Http\Controllers\API\CategoryController::class)->group(function(){ Route::get('categories', 'index')->name('categories.index'); }); });
方法二:配置API Token认证(纯API场景)
如果是给第三方客户端提供API,需要实现Token认证:
- 给
users表添加api_token字段,创建迁移文件:
Schema::table('users', function (Blueprint $table) { $table->string('api_token', 80)->unique()->nullable()->default(null); });
- 运行迁移:
php artisan migrate - 登录时给用户生成/返回
api_token,可在Breeze登录控制器中补充逻辑 - 调用API时,在请求头携带
Authorization: Bearer {你的api_token},或在URL后拼接?api_token={你的api_token}
另外,Laravel 8+推荐使用Sanctum做API认证,它支持Token和SPA认证,适配更现代的API场景,可按需安装配置。
内容的提问来源于stack exchange,提问作者mathius1
相关产品推荐
相关产品推荐

