PHP 防止点击劫持的完整方案
点击劫持(Clickjacking)是一种恶意攻击手段,攻击者通过透明iframe覆盖在合法页面上,诱导用户点击隐藏的按钮,以下是PHP中防止点击劫持的几种方法:

使用X-Frame-Options响应头(最基础)
// 在PHP页面最顶部设置
header('X-Frame-Options: DENY');
// 或
header('X-Frame-Options: SAMEORIGIN');
// 或
header('X-Frame-Options: ALLOW-FROM https://example.com');
三种选项说明:
DENY:完全禁止页面被任何iframe加载SAMEORIGIN:只允许同源页面嵌入iframeALLOW-FROM:指定特定域名可以嵌入(部分浏览器不支持)
使用CSP frame-ancestors指令(最推荐)
// CSP (Content Security Policy) 是目前最有效的方法
header("Content-Security-Policy: frame-ancestors 'self'");
// 或
header("Content-Security-Policy: frame-ancestors https://trusted-domain.com");
// 多个域名
header("Content-Security-Policy: frame-ancestors https://domain1.com https://domain2.com");
// 完全禁止
header("Content-Security-Policy: frame-ancestors 'none'");
完整的PHP函数封装
<?php
function preventClickjacking() {
// 方法1:X-Frame-Options (兼容旧浏览器)
header('X-Frame-Options: SAMEORIGIN');
// 方法2:CSP (现代浏览器)
header("Content-Security-Policy: frame-ancestors 'self'");
// 方法3:通过设置HTTP头禁止缓存(某些代理服务器可能覆盖头部)
header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
}
// 在页面开头调用
preventClickjacking();
?>
在框架层面统一处理
// 使用框架时的统一处理示例(Laravel中)
class Middleware
{
public function handle($request, $next)
{
$response = $next($request);
// 添加安全头
$response->headers->set('X-Frame-Options', 'SAMEORIGIN');
$response->headers->set('Content-Security-Policy', "frame-ancestors 'self'");
return $response;
}
}
JavaScript辅助防护(不推荐单独使用)
// 在PHP生成的页面上添加JavaScript防护
if (top != self) {
top.location = self.location;
}
注意: 这种方法可以被禁用JavaScript的用户绕过,不能单独使用。
综合防护示例
<?php
// 完整的安全防护函数
function applySecurityHeaders() {
// 点击劫持防护
header('X-Frame-Options: SAMEORIGIN');
header("Content-Security-Policy: frame-ancestors 'self'");
// 其他安全头(可选但推荐)
header('X-Content-Type-Options: nosniff');
header('X-XSS-Protection: 1; mode=block');
header('Strict-Transport-Security: max-age=31536000; includeSubDomains');
header('X-Permitted-Cross-Domain-Policies: none');
// 防止缓存敏感页面
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
}
// 调用
applySecurityHeaders();
?>
<!DOCTYPE html>
<html>
<head>安全页面</title>
<script>
// 额外的JavaScript防护(作为辅助)
if (window.top !== window.self) {
window.top.location = window.self.location;
}
</script>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
服务器配置层面的防护
Apache (.htaccess)
<IfModule mod_headers.c>
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Content-Security-Policy "frame-ancestors 'self'"
</IfModule>
Nginx
add_header X-Frame-Options SAMEORIGIN; add_header Content-Security-Policy "frame-ancestors 'self'";
针对特定页面的精细化控制
<?php
// 对不需要被iframe加载的管理页面
if (is_admin_page()) {
header('X-Frame-Options: DENY');
header("Content-Security-Policy: frame-ancestors 'none'");
}
// 对需要被信任域名嵌入的页面
elseif (is_public_api_page()) {
header('X-Frame-Options: ALLOW-FROM https://trusted.com');
header("Content-Security-Policy: frame-ancestors https://trusted.com");
}
// 普通页面
else {
header('X-Frame-Options: SAMEORIGIN');
header("Content-Security-Policy: frame-ancestors 'self'");
}
?>
⚠️ 重要提醒
-
X-Frame-Options 和 CSP 的区别:
- X-Frame-Options 是老方法,部分浏览器支持有限
- CSP
frame-ancestors是更现代、更安全的方法 - 理论上两者都设置,以兼容旧浏览器
-
CSP 兼容性:
frame-ancestors在 Chrome、Firefox、Edge 中支持良好- 不兼容 IE,需要保留 X-Frame-Options
-
最佳实践:
- 尽可能使用
DENY或'none' - 只有在明确需要时才允许特定域名嵌入
- 设置响应头要在输出任何内容之前
- 优先考虑在服务器层面配置
- 尽可能使用
-
测试建议:
# 使用curl检查响应头 curl -I yourwebsite.com
确认响应中存在安全头。
通过以上多重防护措施结合使用,可以最大程度地防止点击劫持攻击,保护网站和用户的安全。