如何保护Laravel API的GET路由仅允许自身Vue前端访问不对外公开
Laravel无登录GET接口防第三方调用解决方案
以下是几种不同安全等级的实现方案,可根据你的需求选择:
方案1:同源校验(零前端改造成本)
适合要求较低的场景,通过校验请求来源是否为你的站点域名实现拦截:
- 第一步:生成校验中间件
执行命令:php artisan make:middleware CheckSameOrigin - 第二步:编写中间件校验逻辑
打开app/Http/Middleware/CheckSameOrigin.php,写入代码:public function handle(Request $request, Closure $next) { $allowedDomains = [ 'https://mywebsite.com', // 你的前端域名 'http://localhost:8080' // 本地开发域名按需添加 ]; $origin = $request->headers->get('Origin'); $referer = $request->headers->get('Referer'); foreach ($allowedDomains as $domain) { if (str_starts_with($origin, $domain) || str_starts_with($referer, $domain)) { return $next($request); } } abort(403); } - 第三步:注册中间件并绑定路由
打开app/Http/Kernel.php,在$routeMiddleware数组里添加:
调整你的路由代码:'check.origin' => \App\Http\Middleware\CheckSameOrigin::class,Route::get('MyFAQS',[\App\Http\Controllers\FaqController::class,'getQuestions'])->middleware('check.origin');
注意:该方案无法防御伪造来源的恶意请求,仅能拦截普通的直接访问
方案2:Laravel签名路由(推荐,安全性高)
利用Laravel自带的签名路由机制,生成带有效期的加密访问链接,第三方无权限生成合法链接:
- 第一步:给路由添加签名中间件和路由名
Route::get('MyFAQS',[\App\Http\Controllers\FaqController::class,'getQuestions']) ->name('faq.questions') ->middleware('signed'); - 第二步:在前端入口Blade模板中注入签名链接
打开你的Vue入口对应的blade文件,在head标签中添加meta标签:
这里设置了签名30分钟过期,可根据需求调整有效期。<meta name="faq_api_url" content="{{ URL::temporarySignedRoute('faq.questions', now()->addMinutes(30)) }}"> - 第三步:调整前端请求逻辑,读取签名链接调用
const faqApiUrl = document.querySelector('meta[name="faq_api_url"]').content; axios.get(faqApiUrl) .then(response => { this.FAQ = response.data; console.log(this.FAQ); }) .catch(error=>{ console.log("can not get FAQ: " + error) })
该方案基本可以拦截99%的恶意爬取,就算第三方拿到过期的签名链接也无法正常访问。
方案3:自定义加密签名校验(适合高安全要求场景)
前后端约定加密规则,动态生成请求校验标识,拦截无有效标识的请求:
- 第一步:前端添加请求拦截器,生成加密签名
可借助js-md5库实现加密,代码示例:import md5 from 'js-md5'; // 密钥请存在前端环境变量中,不要硬编码 const API_SECRET = import.meta.env.VITE_API_SIGN_SECRET; axios.interceptors.request.use(config => { const timestamp = Math.floor(Date.now() / 1000); // 加密规则可自行调整,只要前后端一致即可 const sign = md5(`${timestamp}${API_SECRET}MyFAQS`); config.headers['X-REQ-SIGN'] = sign; config.headers['X-REQ-TIME'] = timestamp; return config; }) - 第二步:后端生成校验中间件,验证签名合法性
中间件逻辑示例:
最后把中间件绑定到对应路由即可。public function handle(Request $request, Closure $next) { $sign = $request->header('X-REQ-SIGN'); $timestamp = $request->header('X-REQ-TIME'); $apiSecret = config('app.api_sign_secret'); // 密钥存在.env配置中 // 校验时间差,防止重放攻击,这里设置5分钟内的请求有效 if (abs(time() - $timestamp) > 300 || !$sign) { abort(403); } // 校验签名是否一致 if (md5($timestamp . $apiSecret . 'MyFAQS') !== $sign) { abort(403); } return $next($request); }
兜底优化:添加频率限制
不管使用哪种方案,都可以给路由添加Laravel自带的频率限制中间件,避免被批量爬取:
Route::get('MyFAQS',[\App\Http\Controllers\FaqController::class,'getQuestions']) ->middleware('throttle:60,1'); // 每分钟最多允许60次请求
内容的提问来源于stack exchange,提问作者Buildermine
相关产品推荐
相关产品推荐

