Laravel 5.6 集成Spatie Permissions时会话超时异常处理问题
Hey, let's break down why you're hitting UnauthorizedException instead of TokenMismatchException when your session times out with Spatie Permissions in Laravel 5.6, and how to fix it.
The Root Cause
Laravel's middleware execution order is the key here. Spatie's role/permission middleware typically runs after the core web middleware, but when a session times out:
- The user becomes unauthenticated
- Spatie's permission middleware checks if the user has the required roles/permissions before the CSRF
VerifyCsrfTokenmiddleware can trigger aTokenMismatchException - Since the user isn't logged in at all, the permission middleware throws an
UnauthorizedExceptionimmediately, skipping the CSRF check entirely.
Fixes to Try
1. Adjust Middleware Execution Order
Make sure the CSRF verification runs before Spatie's permission middleware. This way, session timeouts will trigger TokenMismatchException first.
Open app/Http/Kernel.php and update your web middleware group to place VerifyCsrfToken ahead of any Spatie permission/role middleware:
protected $middlewareGroups = [ 'web' => [ \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, // Place this before Spatie's middleware \Spatie\Permission\Middlewares\RoleMiddleware::class, // Your custom permission middleware here ], ];
2. Handle UnauthorizedException for Session Timeouts
If reordering middleware isn't feasible, modify your Handler.php to detect when an UnauthorizedException is caused by an unauthenticated user (session timeout) and redirect accordingly:
Update your render method in app/Exceptions/Handler.php:
public function render($request, Exception $exception) { // Handle TokenMismatch as before if ($exception instanceof \Illuminate\Session\TokenMismatchException) { session()->flash('warning','Session timeout. Please login again.'); return redirect()->guest(route('login')); } // Handle UnauthorizedException for session timeout cases if ($exception instanceof \Symfony\Component\HttpKernel\Exception\UnauthorizedException) { // Check if user is not authenticated (session expired) if (!auth()->check()) { session()->flash('warning','Session timeout. Please login again.'); return redirect()->guest(route('login')); } // For actual permission denied cases (user is logged in but lacks access) return response()->view('errors.403', [], 403); } // Keep your existing Spatie exception handling here if ($exception instanceof \Spatie\Permission\Exceptions\UnauthorizedException) { // Handle permission-denied for logged-in users return response()->view('errors.403', [], 403); } return parent::render($request, $exception); }
3. Verify Route Middleware Groups
Ensure all your routes that require authentication/permissions are wrapped in the web middleware group. Routes outside this group won't get session or CSRF protection, which can skip the TokenMismatchException entirely.
内容的提问来源于stack exchange,提问作者Shile

