初始化
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* 统一下发 HTTP 安全响应头(纵深防御)。
|
||||
*
|
||||
* 设计说明(零构建架构约束):
|
||||
* - 本站前台使用 Tailwind Play CDN(cdn.tailwindcss.com)与内联 tailwind.config,
|
||||
* 因此 script-src / style-src 必须放行该 CDN 与 'unsafe-inline'。
|
||||
* - 若日后将 Tailwind 改为构建产物并为内联脚本加 nonce,可移除 'unsafe-inline' 收紧 CSP。
|
||||
* - HSTS 仅在「生产环境 + 已启用 HTTPS」时下发,避免本地 http 下浏览器记忆错误。
|
||||
*/
|
||||
class SecurityHeaders
|
||||
{
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$response = $next($request);
|
||||
|
||||
// 禁止 MIME 嗅探(防止被当作可执行内容)
|
||||
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
||||
|
||||
// 防点击劫持(现代浏览器看 frame-ancestors,旧浏览器看 X-Frame-Options)
|
||||
$response->headers->set('X-Frame-Options', 'DENY');
|
||||
|
||||
// Referrer 泄露控制
|
||||
$response->headers->set('Referrer-Policy', 'strict-origin-when-cross-origin');
|
||||
|
||||
// 关闭不必要的浏览器敏感能力
|
||||
$response->headers->set(
|
||||
'Permissions-Policy',
|
||||
"geolocation=(), camera=(), microphone=(), payment=(), usb=(), interest-cohort=()"
|
||||
);
|
||||
|
||||
// 内容安全策略:限制脚本/样式/连接/表单来源,缩小 XSS 影响面
|
||||
$csp = implode('; ', [
|
||||
"default-src 'self'",
|
||||
"script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com",
|
||||
"style-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com",
|
||||
"img-src 'self' data: https:",
|
||||
"font-src 'self' data:",
|
||||
"connect-src 'self'",
|
||||
"frame-ancestors 'none'",
|
||||
"base-uri 'self'",
|
||||
"form-action 'self'",
|
||||
]);
|
||||
$response->headers->set('Content-Security-Policy', $csp);
|
||||
|
||||
// HSTS:仅生产 + HTTPS 时下发
|
||||
if ($request->isSecure() && app()->environment('production')) {
|
||||
$response->headers->set(
|
||||
'Strict-Transport-Security',
|
||||
'max-age=31536000; includeSubDomains; preload'
|
||||
);
|
||||
}
|
||||
|
||||
// 禁止代理/浏览器缓存动态页面(含 CSRF token 的表单页)。
|
||||
// 否则 nginx/浏览器缓存的旧 HTML 会携带过期 _token,提交即触发 419 Page Expired。
|
||||
// 静态资源由 web 服务器直接服务、不经过本中间件,不受影响。
|
||||
$response->headers->set('Cache-Control', 'no-store, no-cache, must-revalidate, private');
|
||||
$response->headers->set('Pragma', 'no-cache');
|
||||
$response->headers->set('Expires', '0');
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user