Laravel Sanctum如何实现单API接口根据Token返回差异化内容?
同一路由兼容授权与未授权请求的解决方案
不需要创建两个路由,直接通过以下两种方式实现:
方法一:控制器内直接判断认证状态
先去掉路由上的强制认证中间件,让所有请求都能进入控制器,再根据用户是否认证返回不同数据:
路由定义
Route::post('/example', ExampleController::class);
控制器逻辑
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class ExampleController extends Controller { public function __invoke(Request $request) { // 检查当前请求是否有通过Sanctum认证的用户 if ($request->user()) { // 给授权用户返回受保护数据 return response()->json([ 'status' => 'success', 'data' => [ 'user_id' => $request->user()->id, 'protected_content' => '仅授权用户可见的专属内容' ] ]); } // 给未授权用户返回公开数据 return response()->json([ 'status' => 'success', 'data' => [ 'public_content' => '所有用户均可查看的公开内容' ] ]); } }
方法二:自定义可选认证中间件(多路由复用场景)
如果多个路由都需要这种“可选认证”逻辑,可以自定义一个中间件,尝试认证但不强制返回401:
1. 创建中间件
执行Artisan命令生成中间件:
php artisan make:middleware OptionalSanctumAuth
2. 编写中间件逻辑
修改生成的app/Http/Middleware/OptionalSanctumAuth.php文件:
<?php namespace App\Http\Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware; class OptionalSanctumAuth extends Middleware { protected function authenticate($request, array $guards) { // 尝试用Sanctum guard认证用户,成功则切换到该guard foreach ($guards as $guard) { if ($this->auth->guard($guard)->check()) { $this->auth->shouldUse($guard); return; } } // 认证失败不抛出401异常,继续执行后续请求 } }
3. 注册中间件别名
在app/Http/Kernel.php的$routeMiddleware数组中添加别名:
protected $routeMiddleware = [ // 其他中间件... 'auth.sanctum.optional' => \App\Http\Middleware\OptionalSanctumAuth::class, ];
4. 路由使用自定义中间件
Route::middleware('auth.sanctum.optional')->post('/example', ExampleController::class);
此时控制器里的逻辑和方法一完全一致,通过$request->user()判断用户状态即可。
内容的提问来源于stack exchange,提问作者Александр Инженер
相关产品推荐
相关产品推荐

