php怎么防止csrf攻击?如何生成验证token防御跨站请求

来源:APP编程网作者:松本一香头衔:网络博主
导读:本期聚焦于小伙伴创作的《php怎么防止csrf攻击?如何生成验证token防御跨站请求》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《php怎么防止csrf攻击?如何生成验证token防御跨站请求》有用,将其分享出去将是对创作者最好的鼓励。

csrf即跨站请求伪造,攻击者会构造恶意页面,诱导已登录目标网站的用户点击,利用用户的登录态发起非预期请求,比如修改密码、转账等操作。php应用中防御csrf攻击最常用的方式就是生成验证token,在合法请求中携带token,服务端校验通过才处理请求。

php怎么防止csrf攻击?如何生成验证token防御跨站请求

csrf攻击的基本原理

用户登录站点A后,浏览器会保存站点A的登录凭证比如session_id。此时如果用户访问恶意站点B,站点B的页面中构造了指向站点A的恶意请求,比如一个隐藏的表单提交或者图片请求,浏览器发起这个请求时会自动带上站点A的cookie,站点A的服务端无法区分这个请求是用户主动发起还是被恶意诱导的,就会执行对应的操作,这就是csrf攻击的核心逻辑。

php生成csrf token的实现

生成token需要满足随机性、唯一性、不可预测性,通常可以结合随机字符串和加密算法实现,以下是生成token的示例代码:

<?php
session_start();

/**
 * 生成csrf token
 * @return string 生成的token字符串
 */
function generate_csrf_token() {
    // 生成32位随机字符串作为token原始内容
    $random_str = bin2hex(random_bytes(16));
    // 存储token到session,用于后续校验
    $_SESSION['csrf_token'] = $random_str;
    // 设置token过期时间,这里设置为30分钟后过期
    $_SESSION['csrf_token_expire'] = time() + 1800;
    return $random_str;
}

// 调用函数生成token
$csrf_token = generate_csrf_token();
echo "生成的csrf token为:" . $csrf_token;
?>

在表单中嵌入csrf token

生成token后,需要在所有涉及数据修改的表单中嵌入token,通常放在隐藏字段中,示例代码如下:

<form method="post" action="update_info.php">
    <input type="hidden" name="csrf_token" value="<?php echo htmlspecialchars($_SESSION['csrf_token']); ?>">
    <label>用户名:<input type="text" name="username"></label><br>
    <label>邮箱:<input type="email" name="email"></label><br>
    <input type="submit" value="提交修改">
</form>

服务端校验csrf token

表单提交后,服务端需要校验请求中携带的token是否合法,校验逻辑包括token是否存在、是否和session中存储的一致、是否过期,示例代码如下:

<?php
session_start();

/**
 * 校验csrf token
 * @param string $input_token 请求中携带的token
 * @return bool 校验通过返回true,否则返回false
 */
function verify_csrf_token($input_token) {
    // 检查session中是否存在token和过期时间
    if (!isset($_SESSION['csrf_token']) || !isset($_SESSION['csrf_token_expire'])) {
        return false;
    }
    // 检查token是否过期
    if (time() > $_SESSION['csrf_token_expire']) {
        // 过期后清除session中的token信息
        unset($_SESSION['csrf_token']);
        unset($_SESSION['csrf_token_expire']);
        return false;
    }
    // 校验token是否一致
    if (hash_equals($_SESSION['csrf_token'], $input_token)) {
        // 校验通过后可以清除当前token,避免重复使用
        unset($_SESSION['csrf_token']);
        unset($_SESSION['csrf_token_expire']);
        return true;
    }
    return false;
}

// 处理表单提交请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $input_token = $_POST['csrf_token'] ?? '';
    if (verify_csrf_token($input_token)) {
        // token校验通过,处理正常的业务逻辑
        $username = $_POST['username'] ?? '';
        $email = $_POST['email'] ?? '';
        echo "用户信息修改成功,用户名为:" . htmlspecialchars($username) . ",邮箱为:" . htmlspecialchars($email);
    } else {
        // token校验失败,返回错误提示
        http_response_code(403);
        echo "请求校验失败,可能存在安全风险,请刷新页面后重试";
    }
}
?>

ajax请求中的token处理

如果是ajax发起的post请求,需要在请求头或者请求参数中携带token,以下是使用原生js发送ajax请求的示例:

// 从页面的meta标签或者隐藏字段中获取token
var csrf_token = document.querySelector('input[name="csrf_token"]').value;

var xhr = new XMLHttpRequest();
xhr.open('POST', 'update_info.php', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
        console.log(xhr.responseText);
    }
};
// 将token作为参数发送
xhr.send('csrf_token=' + encodeURIComponent(csrf_token) + '&username=test&email=test@ipipp.com');

注意事项

  • token要存储在服务端的session中,不要直接存在cookie里,避免被攻击者获取。
  • token要设置合理的有效期,一般建议15到30分钟,过期后需要重新生成。
  • 校验token时要使用hash_equals函数,避免时序攻击导致token被破解。
  • 除了表单请求,所有涉及数据修改的接口比如删除、修改操作都需要添加csrf token校验。
  • 如果是前后端分离的项目,可以将token放在响应头中返回给前端,前端存储后每次请求携带即可。

phpcsrf防御token生成跨站请求防护修改时间:2026-07-19 22:42:36

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。