Laravel API访问限制:仅允许自有前端调用,屏蔽浏览器、Postman等
解决Laravel API访问限制的方案
看起来你已经在用CORS中间件了,但CORS主要是浏览器层面的安全机制,Postman这类工具可以轻松绕过,所以我们需要结合自定义中间件+请求头校验来实现你的所有需求。下面一步步来:
1. 创建自定义访问限制中间件
先创建一个专门处理API访问权限的中间件,用来校验请求的合法性:
php artisan make:middleware RestrictApiAccess
打开生成的app/Http/Middleware/RestrictApiAccess.php,替换成下面的逻辑:
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; class RestrictApiAccess { // 允许的前端域名(替换成你的自有前端域名) protected $allowedOrigins = [ 'https://your-frontend-domain.com', 'http://localhost:3000', // 本地开发环境可以加上 ]; // 自定义校验密钥(前端请求必须携带这个头,值要和这里一致) protected $frontendToken = 'your-secret-frontend-token-here'; public function handle(Request $request, Closure $next): Response { // 处理需求3:隐藏Laravel默认API根页面 if ($request->is('/')) { return response()->json(['message' => 'API is running'], 200); // 或者直接返回404:return abort(404); } // 校验请求来源和合法性 $origin = $request->header('Origin'); $userAgent = $request->header('User-Agent'); $customToken = $request->header('X-Frontend-Token'); // 需求4:禁止Postman等工具访问,同时确保只有自有前端能调用 // 逻辑:浏览器请求(自有前端)会带正确的Origin + 自定义Token;Postman要么伪造不全,要么没有真实的浏览器UA $isValidBrowserRequest = in_array($origin, $this->allowedOrigins) && str_contains($userAgent, 'Mozilla/5.0') // 匹配浏览器的UA特征 && $customToken === $this->frontendToken; // 需求1:禁止浏览器中非自有前端的POST请求 if ($request->isMethod('POST') && !$isValidBrowserRequest) { return response()->json(['error' => 'POST requests are not allowed from this source'], 403); } // 需求2:禁止浏览器中非自有前端的需认证GET请求 if ($request->isMethod('GET') && $request->user() && !$isValidBrowserRequest) { return response()->json(['error' => 'Authenticated GET requests are not allowed from this source'], 403); } // 所有合法请求继续处理 return $next($request); } }
2. 注册中间件
打开app/Http/Kernel.php,把这个中间件添加到api中间件组里(这样所有API请求都会经过它):
protected $middlewareGroups = [ 'api' => [ \App\Http\Middleware\RestrictApiAccess::class, // 加在这里,放在CORS中间件之后 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ], ];
3. 前端配合修改
你的前端需要在所有API请求中携带X-Frontend-Token头,比如用Axios的话:
// 全局配置Axios axios.defaults.headers.common['X-Frontend-Token'] = 'your-secret-frontend-token-here';
这个值要和后端中间件里的$frontendToken完全一致,别泄露出去!
4. 补充优化细节
- CORS配置强化:确保你的CORS配置只允许
$allowedOrigins里的域名,这样浏览器会拦截其他域名的跨域请求。可以在config/cors.php里设置:'allowed_origins' => ['https://your-frontend-domain.com', 'http://localhost:3000'], 'allowed_methods' => ['GET', 'POST', 'PUT', 'DELETE'], // 根据你的需求调整 - User-Agent校验说明:Postman可以伪造UA,但结合Origin和自定义Token,基本能挡住大部分非授权调用;如果要更严格,可以用前端生成签名(比如基于请求时间戳+密钥),后端校验签名,但复杂度会高一些。
- 测试验证:
- 直接在浏览器地址栏访问需认证的API GET地址:应该返回403
- 在浏览器控制台发POST请求到API:返回403
- 用Postman请求API(不管带不带Origin):因为没有
X-Frontend-Token,会被拦截 - 你的自有前端发起请求:正常通过
5. 隐藏Laravel默认API页面的额外方案
如果上面中间件里的根路径处理不够,你可以直接修改routes/api.php,把默认的Route::get('/', function () { ... })删掉,替换成你自己的响应:
Route::get('/', function () { return response()->json(['status' => 'ok', 'message' => 'API is operational'], 200); // 或者直接返回404:abort(404); });
这样就能完全覆盖你提出的4个需求啦!需要注意的是,没有绝对的安全,这种方案能挡住绝大多数非授权访问,如果要更高的安全性,可以考虑加入JWT或者OAuth2的认证机制,结合请求签名。
内容的提问来源于stack exchange,提问作者Jack The Baker
相关产品推荐
相关产品推荐

