如何通过Laravel Sanctum限制API仅允许认证用户查询自身订单数据
Laravel + Sanctum 接口仅允许用户查看自身订单的改造方案
你当前接口的越权问题根源是直接信任前端传入的用户ID参数,没有和当前登录用户身份做校验,可根据业务场景选择以下改造方案:
方案1:移除用户ID参数(推荐,适用于仅允许查自身订单的场景)
既然所有合法请求都只能查询当前登录用户自己的订单,完全不需要前端传入用户ID,直接从Sanctum的认证上下文获取登录用户信息即可,从根源避免参数篡改导致的越权。
1. 修改路由
移除原路由路径中的{id}参数:
Route::group(['middleware' => ['auth:sanctum']], function () { Route::get('/order', [OrdersController::class, 'show']); });
2. 修改控制器方法
直接复用你Blade场景的实现逻辑即可,同时因为经过auth:sanctum中间件的请求必然是已认证的,不需要额外捕获用户查询异常:
public function show() { // 直接从认证实例获取当前登录用户,不会被前端参数篡改 return auth()->user()->orders; }
如果需要保留错误响应的写法也可以调整为:
public function show() { try { return auth()->user()->orders; } catch (\Exception $e) { // 注意修正原代码中的message拼写错误 return response()->json(['message' => "无法获取当前用户订单"], 400); } }
方案2:保留用户ID参数(适用于需要支持管理员查询其他用户订单的场景)
如果业务要求保留路径中的用户ID参数,需要在查询前增加身份校验,判断传入的用户ID是否和当前登录用户ID一致,不一致直接返回无权限:
public function show($uid) { // 非管理员用户只能查自己的订单 if (!auth()->user()->is_admin && $uid != auth()->id()) { return response()->json(['message' => "无权查看其他用户订单"], 403); } try { $user = User::findOrFail($uid); return $user->orders; } catch (\Exception $e) { return response()->json(['message' => "无法获取对应用户订单"], 400); } }
进阶:统一权限管控方案
如果项目后续权限逻辑复杂度高,推荐使用Laravel官方的策略类(Policy) 统一管理全项目的权限校验逻辑,避免每个控制器重复编写校验代码:
- 生成订单策略类:
php artisan make:policy OrderPolicy --model=Order - 在策略类中定义查看权限校验逻辑:
public function view(User $user, User $targetUser) { // 管理员可查看所有,普通用户仅可查看自己 return $user->is_admin || $user->id === $targetUser->id; }
- 在
app/Providers/AuthServiceProvider.php中注册策略后,即可在控制器中直接调用校验:
public function show($uid) { $targetUser = User::findOrFail($uid); // 权限校验不通过会自动返回403响应 $this->authorize('view', $targetUser); return $targetUser->orders; }
内容的提问来源于stack exchange,提问作者Osama Mohammed
相关产品推荐
相关产品推荐

