php防御csrf攻击的核心做法是在表单或请求中嵌入服务端生成的唯一token,并在接收请求时校验该token的有效性。具体实现通常涉及在session中存储一个随机字符串作为token,将其渲染到前端表单的隐藏字段中,后端在处理逻辑前比对session中的值与用户提交的值是否一致。若两者匹配则放行,否则拒绝请求并返回错误。这种机制确保了请求来源的合法性,防止了跨站请求伪造。

如何生成并存储CSRF Token
生成CSRF Token的关键在于使用加密安全的随机数生成器创建唯一标识符,并将其安全地存储在用户的Session中。在PHP中,可以使用bin2hex(random_bytes(32))来生成一个32字节的十六进制字符串,这提供了足够的熵值以防止预测。存储时,应确保Session已正确启动,并将生成的Token赋值给$_SESSION['csrf_token']。这样做的结果是每个用户会话都会拥有一个独立的、难以猜测的Token,为后续的校验奠定基础。

$token = bin2hex(random_bytes(32)); session_start(); $_SESSION['csrf_token'] = $token; echo $token;
上述代码首先启动Session,然后生成一个随机的32字节字符串并转换为十六进制。生成的Token被存入$_SESSION数组中,键名为csrf_token。最后输出该Token以便在前端使用。此过程保证了Token的唯一性和安全性,是防御CSRF的第一步。
如何在表单中嵌入并校验Token
将Token嵌入表单和在校验请求时的关键在于保持前后端数据的一致性。在前端,需要将上一步生成的Token放入一个隐藏的字段中,例如
// 假设 $token 已从 Session 获取
if (isset($_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
// 处理业务逻辑
echo "Request is valid.";
} else {
http_response_code(403);
echo "Invalid CSRF token.";
}
这段代码展示了完整的校验流程。首先检查$_POST中是否存在csrf_token字段,然后使用hash_equals()进行恒定时间比较,以确保安全性。如果校验通过,则执行后续的业务逻辑;否则,返回403 Forbidden状态码。这种方法有效阻止了未经授权的跨站请求。
如何处理Token失效或重复提交的情况
在实际应用中,可能会遇到Token失效或用户重复提交表单的情况。Token失效通常发生在Session过期或手动清除后,此时校验会失败,程序应提示用户重新登录或刷新页面。对于重复提交,可以在校验通过后立即销毁当前的Token并生成一个新的Token存入Session,即“一次性Token”策略。这样,即使攻击者截获了之前的请求包,也无法再次使用相同的Token发起请求。此外,还可以结合验证码或操作确认弹窗来增强安全性。
session_start();
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['csrf_token']) && hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
// 处理业务逻辑
echo "Success.";
// 生成新Token以防重放
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
} else {
http_response_code(403);
echo "Invalid or expired token.";
}
}
此代码片段演示了一次性Token的实现。在成功处理POST请求后,立即更新$_SESSION['csrf_token']为新的随机值。这意味着旧的Token即刻失效,无法用于后续的请求。这种机制极大地增加了攻击者利用截获Token的难度,进一步提升了系统的安全性。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











