Laravel 10项目如何限制API接口仅内部访问,禁止外部公开访问?
最佳实现方案
针对你的需求,核心思路是确保API请求仅来自应用内部的视图/React组件,拦截外部直接访问。以下是几种可靠的实现方式,按推荐优先级排序:
1. 迁移API路由到web.php,复用Laravel自带的CSRF与会话保护
这是最简单高效的方案,利用Laravel web 中间件组的内置安全机制:
步骤:
将需要保护的API路由从
api.php迁移到web.php,比如:// web.php use App\Http\Controllers\ProductController; Route::get('/api/product/{id}', [ProductController::class, 'show']);(
web中间件组默认已包含CSRF保护、会话管理,无需额外添加)在Blade视图中把CSRF令牌注入全局变量,供React使用:
<script> window.csrfToken = '{{ csrf_token() }}'; </script> <div id="react-app"></div>配置Axios自动携带CSRF令牌和AJAX标识头:
import axios from 'axios'; // 全局配置 axios.defaults.headers.common = { 'X-CSRF-TOKEN': window.csrfToken, 'X-Requested-With': 'XMLHttpRequest' }; // 发起请求示例 axios.get('/api/product/1') .then(res => console.log(res.data));可选:添加AJAX请求检查(拦截地址栏直接访问)
创建一个简单的中间件验证请求是否为AJAX:php artisan make:middleware OnlyAjax中间件逻辑:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; class OnlyAjax { public function handle(Request $request, Closure $next) { if (!$request->ajax()) { return response()->json(['message' => '未授权访问'], 401); } return $next($request); } }注册中间件后,给路由添加:
Route::get('/api/product/{id}', [ProductController::class, 'show'])->middleware('only.ajax');
优势:
- 复用Laravel原生安全机制,无需从零构建验证逻辑
- 会话与CSRF令牌绑定,外部请求无法伪造有效凭证
- 实现成本极低,代码改动少
2. 自定义中间件验证内部请求(适合保留api.php路由的场景)
如果不想迁移路由,可以给api路由添加自定义中间件,验证请求是否来自内部:
步骤:
创建自定义中间件:
php artisan make:middleware InternalApiAccess编写中间件逻辑(结合会话、CSRF、AJAX检查):
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Illuminate\Support\Facades\Session; class InternalApiAccess { public function handle(Request $request, Closure $next) { // 验证会话存在且CSRF令牌匹配 if (!Session::exists('_token') || !$request->hasHeader('X-CSRF-TOKEN') || $request->header('X-CSRF-TOKEN') !== csrf_token()) { return response()->json(['message' => '未授权访问'], 401); } // 验证是AJAX请求(拦截地址栏直接访问) if (!$request->ajax()) { return response()->json(['message' => '未授权访问'], 401); } return $next($request); } }在
app/Http/Kernel.php注册中间件:protected $routeMiddleware = [ // ... 'internal.api' => \App\Http\Middleware\InternalApiAccess::class, ];给需要保护的api路由添加中间件:
// api.php Route::get('/product/{id}', [ProductController::class, 'show'])->middleware('internal.api');后续步骤同方案1:Blade注入CSRF令牌,Axios配置携带头
额外防护建议
为了进一步防止批量爬取,可以添加以下辅助措施:
- 请求频率限制:给路由添加Laravel自带的
throttle中间件,比如->middleware('throttle:10,1')(每分钟最多10次请求) - Referer校验(辅助):在中间件中添加Referer头检查,确认请求来源是自身域名(注意:Referer可伪造,仅作为补充验证)
$referer = parse_url($request->headers->get('Referer') ?? ''); if (!isset($referer['host']) || $referer['host'] !== parse_url(config('app.url'))['host']) { return response()->json(['message' => '未授权访问'], 401); }
内容的提问来源于stack exchange,提问作者rfadeout
相关产品推荐
相关产品推荐

