1.检查ORIGIN标头
根据OWASP的指定,这还不够,但建议:
尽管从您自己的浏览器中欺骗任何标头很简单,但除非通过XSS漏洞,否则在CSRF攻击中通常是不可能的。这就是为什么检查标头是CSRF防御中合理的第一步,但是由于它们并不总是存在,因此通常不能单独考虑将其视为足够的防御。
而由Mozilla:
Origin标头被认为有助于防止JSON数据盗用和CSRF攻击。Origin提供的信息(一些上下文请求创建信息)应向Web服务器提供有关请求可信度的提示[…]
检查
HTTP_ORIGIN标题可以写成:
header('Content-Type: application/json'); if (isset($_SERVER['HTTP_ORIGIN'])) { $address = 'http://' . $_SERVER['SERVER_NAME']; if (strpos($address, $_SERVER['HTTP_ORIGIN']) !== 0) { exit(json_enpre([ 'error' => 'Invalid Origin header: ' . $_SERVER['HTTP_ORIGIN'] ])); } } else { exit(json_enpre(['error' => 'No Origin header'])); }1.(之二)检查REFERER标头
再次从OWASP:
如果没有Origin头
,请确认Referer头中的主机名与站点的来源匹配。检查引荐是防止嵌入式网络设备上CSRF的一种常用方法,因为它不需要每个用户状态。.这种CSRF缓解方法也常用于未经身份验证的请求[…]
使用来检查,
HTTP_REFERER在PHP中也非常简单
$_SERVER['HTTP_REFERER'],您可以使用来更新上面的代码。
请务必 始终进行真正的检查:不要只检查 example.com 或 _api.example.com, 而不要检查完整的
https://example.com 。为什么呢 因为您可以使用诸如
_api.example.com.hacker.com之 类的来源来欺骗此检查。
2.生成CSRF令牌
简而言之,已经给出了一个专门针对PHP的解释清楚的答案:
- 生成令牌:
session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); }通过meta(例如Github)将其添加到生成的视图中:
<meta name="csrf-token" content="<?= $_SESSION['csrf_token'] ?>">
设置jQuery ajax调用以包含此令牌:
$.ajaxSetup({ headers : { 'CsrfToken': $('meta[name="csrf-token"]').attr('content') } });- 服务器端检查您的AJAX请求:
session_start(); if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } header('Content-Type: application/json'); $headers = apache_request_headers(); if (isset($headers['CsrfToken'])) { if ($headers['CsrfToken'] !== $_SESSION['csrf_token']) { exit(json_enpre(['error' => 'Wrong CSRF token.'])); } } else { exit(json_enpre(['error' => 'No CSRF token.'])); }大多数PHP框架都有自己的CSRF实现,或多或少都基于相同的原理。
4.保护您的服务器
- 限制您的请求数。
- 尽可能使用https。
- 阻止错误的查询。
- 保护POST请求。
5.永远不要相信用户输入
正如@
blue112所说,这是最基本的安全原则之一。



