Laravel 5禁用CSRF令牌遇异常,多端POST请求问题求解
Hey there, let's work through this CSRF problem you're hitting with your Laravel learning service. It's super common when dealing with non-browser clients, so let's break down the fixes and figure out why that 500 error popped up.
First: Fix the 500 Error When Adding Routes to $except
When you added '/*' or '/api/article/create' to the $except array in VerifyCsrfToken.php and got a 500, it's almost always one of two things:
- Syntax mistake in the file: Double-check your array formatting—make sure you have commas between entries, no missing quotes, and the file ends with proper PHP syntax.
- Conflict with other routes: If you excluded
/*, you're disabling CSRF for all routes, including Laravel's built-in auth routes (login/register) which rely on CSRF. That can break those pages and throw a 500.
Correct VerifyCsrfToken Configuration
Here's the proper way to exclude your API routes (avoid /* unless you're 100% sure you don't need CSRF for any browser routes):
<?php namespace App\Http\Middleware; use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; class VerifyCsrfToken extends Middleware { /** * The URIs that should be excluded from CSRF verification. * * @var array<int, string> */ protected $except = [ // Exclude a single API route '/api/article/create', // Or exclude all routes under the /api prefix (better for API-only endpoints) '/api/*', ]; }
After updating, clear your Laravel cache just in case:
php artisan config:clear
If you still get a 500, check your Laravel logs at storage/logs/laravel.log—it'll show the exact error (like a missing comma or route conflict).
Better Solution: Use API Token Authentication (Recommended)
CSRF protection is designed for browser-based requests where sessions are shared. For non-browser clients like WinForms, Android, or even Angular (if it's a separate SPA), API token authentication is more secure and the Laravel-recommended approach. Let's use Laravel Sanctum (lightweight and perfect for learning projects):
Step 1: Install & Configure Sanctum
- Install the package:
composer require laravel/sanctum - Publish Sanctum's configuration and migrations:
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" - Run the migrations to create the token table:
php artisan migrate - Add the
HasApiTokenstrait to yourUsermodel:// app/Models/User.php use Laravel\Sanctum\HasApiTokens; class User extends Authenticatable { use HasApiTokens, HasFactory, Notifiable; // ... rest of your model code }
Step 2: Protect Your API Routes
In routes/api.php, wrap your routes with the auth:sanctum middleware to require a valid token:
use App\Http\Controllers\ArticleController; Route::middleware('auth:sanctum')->group(function () { Route::post('/article/create', [ArticleController::class, 'create']); // Add other API routes here });
Step 3: Get & Use Tokens in Clients
- First, create a login endpoint to issue tokens (add this to
routes/api.php):Route::post('/login', function (Request $request) { $credentials = $request->only('email', 'password'); if (!Auth::attempt($credentials)) { return response()->json(['message' => 'Invalid credentials'], 401); } $user = Auth::user(); $token = $user->createToken('client-token')->plainTextToken; return response()->json(['token' => $token]); }); - Your clients (WinForms/Android/Angular) will first send a POST request to
/api/loginwith the user's credentials to get the token. - For subsequent POST requests (like
/api/article/create), include the token in the request header:Authorization: Bearer YOUR_TOKEN_HERE
This way, you don't need to worry about CSRF tokens at all for API requests, and it's way more secure than disabling CSRF entirely.
Alternative: Fetch CSRF Token for Non-Browser Clients
If you really want to keep using CSRF (not recommended for APIs), you can create an endpoint to return the CSRF token, then have your clients include it in their requests:
- Add this route to
routes/api.phporroutes/web.php:Route::get('/csrf-token', function () { return response()->json(['csrf_token' => csrf_token()]); }); - Clients will first send a GET request to
/csrf-tokento retrieve the token. - When sending POST requests, include the token either:
- In the request header:
X-CSRF-TOKEN: YOUR_CSRF_TOKEN - Or as a form field:
_token=YOUR_CSRF_TOKEN
- In the request header:
Note: This requires handling sessions in non-browser clients, which can be tricky (you'll need to store and send cookies), so it's not ideal for multi-client setups.
内容的提问来源于stack exchange,提问作者Bảo Vưu

