
本文介绍如何在 laravel 中使用自定义中间件校验 http referer,确保仅当用户从指定 url 跳转至登录页时才允许访问;否则直接中断请求、不渲染任何视图(包括登录页),实现严格来源控制。
本文介绍如何在 laravel 中使用自定义中间件校验 http referer,确保仅当用户从指定 url 跳转至登录页时才允许访问;否则直接中断请求、不渲染任何视图(包括登录页),实现严格来源控制。
在 Laravel 应用中,实现“仅允许来自特定 URL 的请求访问登录页”这一需求,最合理、最可控的方式是使用全局中间件(Global Middleware)或分组中间件(Web Group Middleware),而非在控制器或路由闭包中零散处理。这是因为我们需要在请求进入业务逻辑(如 LoginController)之前就完成来源校验,并在不满足条件时立即终止响应——避免任何视图渲染(包括 404 或错误页面),达到“完全不可达”的效果。
✅ 正确做法:创建并注册 Referrer 校验中间件
首先,在命令行中生成中间件:
php artisan make:middleware CheckReferrer
然后编辑 app/Http/Middleware/CheckReferrer.php,完整实现如下:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class CheckReferrer
{
// 允许的来源域名(支持通配符或精确匹配)
protected array $allowedHosts = [
'https://trusted-source.com',
'https://partner.example.org',
'https://myapp.internal', // 示例内网地址
];
public function handle(Request $request, Closure $next): Response
{
$referer = $request->headers->get('referer');
// 若无 Referer(如直接输入 URL、书签访问、cURL 无头请求),一律拒绝
if (empty($referer)) {
abort(403, 'Access denied: Missing referer');
}
// 解析 Referer 的 host 部分(避免协议/路径干扰)
$parsed = parse_url($referer);
if (!$parsed || !isset($parsed['host'])) {
abort(403, 'Access denied: Invalid referer format');
}
$refererHost = $parsed['scheme'] . '://' . $parsed['host'];
// 检查是否在白名单中(严格匹配)
if (!in_array($refererHost, $this->allowedHosts, true)) {
// ⚠️ 关键:不返回视图,不重定向,直接终止响应
// 可选:返回空响应(HTTP 204)或直接 abort(403)
abort(403, 'Access denied: Unauthorized referrer');
}
return $next($request);
}
}
? 注意:
abort(403)会触发 Laravel 默认的 403 响应(通常为resources/views/errors/403.blade.php)。若你希望彻底不显示任何 HTML 内容(连错误页都不渲染),可改为:
Laravel Cloud下载Laravel Cloud(cloud.laravel.com)。此技能用于处理所有 Laravel Cloud 请求,包括搜索和读取数据。只要任务涉及 Laravel Cloud,即使用此技能。
return response('', 403)->withoutCookie('XSRF-TOKEN'); // 空响应体 + 403 状态码
? 注册中间件到 Web 请求栈
打开 app/Http/Kernel.php,将中间件添加到 $middlewareGroups['web'] 数组首位(确保早于 StartSession、Authenticate 等中间件):
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,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
// ? 插入此处:确保在认证/会话前拦截
\App\Http\Middleware\CheckReferrer::class,
],
];
✅ 此配置将使该中间件作用于所有 web 路由(即默认 Route::middleware('web') 的所有路由,包括 /login)。
? 验证与测试建议
- ✅ 使用浏览器开发者工具 → Network → 手动修改
Referer请求头测试; - ✅ 使用
curl模拟不同来源:curl -H "Referer: https://trusted-source.com/dashboard" http://localhost/login curl -H "Referer: https://evil.com" http://localhost/login # 应返回 403 curl http://localhost/login # 无 Referer,应被拒绝
- ❌ 不要依赖
url()->previous()—— 它读取的是 session 中存储的上一页(可能被篡改或为空),不可用于安全校验; - ❌ 避免在
LoginController::showLoginForm()中判断 —— 此时视图已准备渲染,无法真正“隐藏登录页”。
⚠️ 重要注意事项
- Referer 可被客户端伪造,因此该方案适用于「防止误点/非授权跳转」等场景,不替代服务端身份认证或 API 签名验证;
- 若需更高安全性(如 SSO、OAuth 回调),应结合 token、state 参数、签名验证等机制;
- 生产环境建议配合 CSP(
referrerpolicy="strict-origin-when-cross-origin")增强 Referer 行为一致性; - 对于 SPA 前端(如 Vue/React),注意其路由跳转不会自动携带 Referer,需在
router.push()前手动设置document.referrer(受限于浏览器策略,实际可行性低),更推荐后端透传 token 或使用?source=xxx查询参数辅助校验。
通过此中间件方案,你实现了轻量、可维护、符合 Laravel 架构规范的来源访问控制,既满足“非白名单来源不显示任何内容”的业务要求,又保持了应用的安全边界与可扩展性。











