Files
cloud-chip.cn/app/Http/Middleware/SecurityHeaders.php
T
2026-08-08 18:27:38 +08:00

71 lines
2.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* 统一下发 HTTP 安全响应头(纵深防御)。
*
* 设计说明(零构建架构约束):
* - 本站前台使用 Tailwind Play CDNcdn.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;
}
}