PHP 如何有效防止跨站请求伪造 (CSRF)

How to prevent Cross-site request forgery (CSRF) effectively in PHP

我试图通过以下方式阻止 CSRF in

  1. 在每一页的开头生成一个 $_SESSION['token']。我已经知道使用 $_COOKIES 是完全错误的,因为它们会为每个请求自动发送。

  2. 在每个 <form> 中,附加以下输入:<input type="hidden" name="t" value="<?php echo '$_SESSION['token']; ?>">

  3. $_SESSION['token']; 通过 $_POST['t']

  4. 验证

现在我有几个小问题:

非常感谢您。

Is this a good way to prevent CSRF?

是的。这样做是为了强制客户端在对您的表单处理程序执行 POST 之前在表单上执行 GET。这可以防止现代浏览器中的 CSRF ,因为浏览器会阻止客户端 Javascript 向外部域发出 XHR GET 请求,因此第 3 方无法在他们的网站上模仿您的表单并成功获得有效的提交令牌。

When another page is opened as well that sets the same $_SESSION variable, the previous (still open) page becomes invalid, how to prevent this?

允许多个令牌同时有效,在会话中保留一组有效令牌。或者,根本不存储任何令牌,而是使用令牌签名方案。我已经涉足并解释了 here。备选方案 2:在整个会话中只使用一个令牌,而不会使令牌无效。 (在评论中向@SilverlightFox 致敬)

For forms this method is clear, but how to handle normal links? Is it necessary to append the token to each link as well?

没有。您只需要保护 POST 个请求,因为 大概只有 POST 个请求可以更改敏感数据 (眨眼,眨眼,您坚持 REST 约定,对吧? !) 和 XHR GET 请求已在浏览器端被阻止。

当黑客试图从经过身份验证的用户发送虚假请求时,就会发生 CSRF 攻击。通常这种攻击发生 在网上商店或银行。

防止php中的csrf攻击我们可以: 1 = 创建检查登录函数: 如果登录会话设置为 true Ok,如果不是 false 则 return 到登录页面。 2 = 创建一个随机 makeToken 哈希函数:base64_encode(md5(microtime())) 并将其保存到会话中,并创建一个输入隐藏类型,其中包含令牌名称和带有名称令牌函数的值。 3 = 创建一个 checkTocken 函数并检查它,如果它等于 makeToken 函数,然后使用 unset 函数取消设置会话,并创建一个新的。