PHP-实例-CSRF

发布于:2024-07-07 ⋅ 阅读:(37) ⋅ 点赞:(0)

1 需求

按照用途分类:

  • 会话(会话ID和会话令牌 二选一)
    • 会话ID:服务器侧自动生成,自动存储在cookie中,需要在服务器侧存储
    • 会话令牌:服务器侧手动生成,手动存储在cookie中,不需要再服务器侧存储
  • CSRF
    • CSRF令牌:

按照存储位置分类:

  • 服务器侧
    • $_SESSION
  • 浏览器侧
    • cookie
    • 隐藏控件

2 语法


3 示例

在 PHP 中,防范 CSRF(跨站请求伪造)攻击的一种常见方法是使用令牌(token)验证。这个令牌通常是一个随机生成的字符串,它在表单提交时与用户的会话(session)相关联。下面是一个简单的 PHP 示例,演示了如何防范 CSRF 攻击:

  1. 生成 CSRF 令牌

在会话开始时,生成一个随机的 CSRF 令牌并将其存储在会话中。

session_start();

// 生成 CSRF 令牌
if (!isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
  1. 在表单中包含 CSRF 令牌

在 HTML 表单中,将 CSRF 令牌作为隐藏字段或作为请求头的一部分包含在内。

<form action="submit.php" method="post">
<!-- 其他表单字段 -->

<!-- CSRF 令牌作为隐藏字段 -->
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token']; ?>">

<!-- 提交按钮 -->
<button type="submit">Submit</button>
</form>

或者,你可以使用 JavaScript 将 CSRF 令牌作为请求头的一部分发送:

// 假设你已经在某处将 CSRF 令牌存储在 JavaScript 变量中
var csrfToken = '...'; // 从 cookie、localStorage 或其他地方获取

// 使用 AJAX 发送请求时,将 CSRF 令牌作为请求头的一部分发送
$.ajax({
url: 'submit.php',
type: 'POST',
data: { /* 其他数据 */ },
headers: {
'X-CSRF-Token': csrfToken
},
success: function(response) {
// 处理响应
}
});
  1. 验证 CSRF 令牌

在服务器端,验证接收到的 CSRF 令牌是否与会话中的令牌匹配。

session_start();
// 检查是否提交了 CSRF 令牌
if (isset($_POST['csrf_token']) && $_POST['csrf_token'] === $_SESSION['csrf_token']) {
// CSRF 令牌验证成功,处理表单数据
// ...
} else {
// CSRF 令牌验证失败,可能是 CSRF 攻击
// 可以采取相应的措施,如记录日志、返回错误消息等
die('Invalid CSRF token.');
}

如果你使用的是 AJAX 请求并通过请求头发送 CSRF 令牌,你可以在服务器端通过 $_SERVER['HTTP_X_CSRF_TOKEN'] 来获取它并进行验证。

请注意,这只是一个简单的示例,用于说明如何防范 CSRF 攻击。在实际应用中,你可能还需要考虑其他安全措施,如使用 HTTPS 来加密通信、限制请求的来源等。


4 参考资料

CSRF 令牌(通常称为 CSRF token)通常是在用户会话(session)开始时生成,并在整个会话期间保持不变。这意味着,在用户的单个会话中,CSRF 令牌是唯一的并且相同的,但不同的用户会话或不同的浏览器会话会有不同的 CSRF 令牌。

这是 CSRF 令牌的一个典型实现方式:

  1. 当用户首次访问受保护的页面或应用时,服务器会为该用户会话生成一个随机的 CSRF 令牌,并将其存储在会话数据(如 PHP 的 $_SESSION)中。
  2. 同时,服务器会将这个 CSRF 令牌嵌入到发送到客户端的页面中,通常是通过一个隐藏的表单字段或者 cookie。
  3. 当用户提交表单时,客户端会将 CSRF 令牌包含在请求中(通常是通过表单字段或自定义的 HTTP 请求头)。
  4. 服务器在接收到请求时,会检查请求中的 CSRF 令牌是否与会话数据中的令牌匹配。如果匹配,则继续处理请求;如果不匹配,则拒绝请求,并可能记录一个安全事件。

由于 CSRF 令牌是在会话开始时生成的,并且通常在整个会话期间保持不变,因此服务器可以在多个请求之间验证相同的 CSRF 令牌。这样可以确保只有知道当前会话 CSRF 令牌的用户(即同一浏览器的同一用户会话)才能提交有效的表单请求。

然而,值得注意的是,有些实现可能会选择在每次请求时都生成新的 CSRF 令牌。虽然这可以提供更高的安全性(因为即使 CSRF 令牌在某个时间点被泄露,它也会在很短时间内失效),但它也会增加实现的复杂性,并可能导致一些额外的问题(如需要在多个页面之间传递和同步 CSRF 令牌)。因此,在大多数情况下,每个会话一个 CSRF 令牌是足够安全的,并且更容易实现和管理。


网站公告

今日签到

点亮在社区的每一天
去签到