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

如何捕获Laravel Sanctum的MissingAbilityException并获取缺失权限?

解决Laravel 11 Sanctum MissingAbilityException无法捕获的问题

问题原因

Laravel的异常处理器会自动将MissingAbilityException包装为AccessDeniedHttpException,导致你直接捕获MissingAbilityException的逻辑无法触发,最终只能捕获到外层的AccessDeniedHttpException,且无法直接获取缺失的权限信息。

解决方案

方法一:通过原始异常获取MissingAbilityException

直接捕获AccessDeniedHttpException,然后通过getPrevious()方法获取被包装的MissingAbilityException实例,从而拿到缺失的权限列表:

use Laravel\Sanctum\Exceptions\MissingAbilityException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use Illuminate\Http\Request;

->withExceptions(function (Exceptions $exceptions) {
    $exceptions->render(function (AccessDeniedHttpException $exception, Request $request) {
        // 检查原始异常是否为Sanctum的MissingAbilityException
        if ($exception->getPrevious() instanceof MissingAbilityException) {
            $missingException = $exception->getPrevious();
            $missingAbilities = $missingException->abilities();
            
            return response()->json([
                'message' => sprintf('You don\'t have the "%s" permission', implode(', ', $missingAbilities)),
                'missing_abilities' => $missingAbilities
            ], 403);
        }

        // 处理其他AccessDenied场景
        return response()->json([
            'message' => $exception->getMessage()
        ], 403);
    });
});

方法二:自定义Sanctum权限中间件

绕过Laravel的异常包装逻辑,直接在自定义中间件中返回带权限信息的JSON响应:

  1. 创建自定义中间件app/Http/Middleware/CheckSanctumAbilities.php:
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class CheckSanctumAbilities
{
    public function handle(Request $request, Closure $next, ...$abilities): Response
    {
        if (! $request->user() || ! $request->user()->currentAccessToken()->can($abilities)) {
            return response()->json([
                'message' => sprintf('You don\'t have the "%s" permission', implode(', ', $abilities)),
                'missing_abilities' => $abilities
            ], 403);
        }

        return $next($request);
    }
}
  1. 在bootstrap/app.php中注册中间件别名:
$middleware->alias([
    // ...
    'sanctum.abilities' => \App\Http\Middleware\CheckSanctumAbilities::class,
]);
  1. 路由中使用自定义中间件:
Route::middleware(['auth:sanctum', 'sanctum.abilities:foo'])->group(function () {
    Route::get('/foo', [FooController::class, 'foo']);
});

内容的提问来源于stack exchange,提问作者Don't Panic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:43:24