如何正确实现 CSRF Token 验证以防止跨站请求伪造攻击

来源:AI大模型作者:弥生美月头衔:网络博主
导读:本期聚焦于小伙伴创作的《如何正确实现 CSRF Token 验证以防止跨站请求伪造攻击》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《如何正确实现 CSRF Token 验证以防止跨站请求伪造攻击》有用,将其分享出去将是对创作者最好的鼓励。

跨站请求伪造攻击中,攻击者会利用用户已登录的身份,诱导用户访问恶意页面触发非预期请求,比如修改密码、转账等操作。要防御这类攻击,CSRF Token验证是最成熟可靠的方案之一,核心思路是让每个合法请求都携带服务端颁发的唯一随机令牌,服务端校验令牌合法性后再处理请求。

如何正确实现 CSRF Token 验证以防止跨站请求伪造攻击

CSRF Token的工作原理

CSRF Token的本质是一个随机生成的字符串,由服务端在用户会话建立时生成,与用户会话绑定。合法请求发起时,令牌会随请求参数或请求头传递到服务端,服务端对比请求中的令牌和会话中存储的令牌是否一致,一致则认为是合法请求,否则拒绝处理。

攻击者无法获取目标用户的CSRF Token,因此无法构造出包含合法令牌的恶意请求,也就无法完成跨站请求伪造攻击。

后端实现CSRF Token验证

1. 生成与存储CSRF Token

用户登录成功后,服务端生成随机CSRF Token,存储到用户的会话中,同时将令牌返回给前端。以下是Java Spring Boot框架的生成示例:

import java.util.UUID;
import javax.servlet.http.HttpSession;

public class CsrfTokenUtil {
    // 生成CSRF Token并存入会话
    public static String generateToken(HttpSession session) {
        String token = UUID.randomUUID().toString().replace("-", "");
        // 将会话中存储的令牌键设为csrf_token
        session.setAttribute("csrf_token", token);
        return token;
    }
}

2. 校验CSRF Token

服务端在处理敏感请求时,从请求参数或请求头中获取令牌,和会话中存储的令牌对比。以下是校验逻辑的示例:

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class CsrfTokenUtil {
    // 校验CSRF Token合法性
    public static boolean validateToken(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session == null) {
            return false;
        }
        // 从请求头中获取令牌,也可以从请求参数获取
        String requestToken = request.getHeader("X-CSRF-TOKEN");
        if (requestToken == null) {
            requestToken = request.getParameter("csrf_token");
        }
        String sessionToken = (String) session.getAttribute("csrf_token");
        // 令牌为空或者不匹配则返回false
        if (sessionToken == null || !sessionToken.equals(requestToken)) {
            return false;
        }
        return true;
    }
}

3. 拦截器配置

可以通过拦截器统一处理所有需要校验的请求,避免在每个接口中重复编写校验逻辑。以下是Spring Boot拦截器的配置示例:

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CsrfInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 放行GET等非修改请求,只校验POST、PUT、DELETE等修改请求
        String method = request.getMethod();
        if ("GET".equalsIgnoreCase(method) || "HEAD".equalsIgnoreCase(method) || "OPTIONS".equalsIgnoreCase(method)) {
            return true;
        }
        boolean isValid = CsrfTokenUtil.validateToken(request);
        if (!isValid) {
            response.setStatus(403);
            response.getWriter().write("CSRF Token验证失败");
            return false;
        }
        return true;
    }
}

前端传递CSRF Token

1. 表单请求传递

如果是表单提交,可以在表单中隐藏一个input标签存放CSRF Token,提交时随表单数据一起传递:

<form action="/update-password" method="post">
    <!-- 隐藏的CSRF Token字段 -->
    <input type="hidden" name="csrf_token" value="${csrfToken}">
    <input type="password" name="newPassword" placeholder="请输入新密码">
    <button type="submit">修改密码</button>
</form>

2. Ajax请求传递

如果是Ajax请求,可以将CSRF Token放到请求头中传递,以下是原生JavaScript的示例:

// 假设从页面元标签中获取CSRF Token
const csrfToken = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
fetch('/api/transfer', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRF-TOKEN': csrfToken
    },
    body: JSON.stringify({
        amount: 100,
        targetAccount: '123456'
    })
})
.then(response => {
    if (response.ok) {
        console.log('请求处理成功');
    } else {
        console.log('请求处理失败');
    }
});

实现注意事项

  • CSRF Token必须是随机生成的高熵值字符串,避免使用可预测的序列,防止被攻击者猜测。
  • Token要和用户的会话绑定,不同用户的Token不能通用,用户退出登录后要清除会话中的Token。
  • 敏感操作对应的Token可以设置一次性使用,使用后立即失效并生成新的Token,进一步提升安全性。
  • 不要在Cookie中直接存储CSRF Token,避免被攻击者通过XSS攻击获取,建议存储在服务端会话或者前端的不可被脚本随意读取的存储位置。
  • 对于文件上传等包含特殊Content-Type的请求,要确保Token能够正确传递,避免因为请求格式问题导致校验失败。
CSRF Token验证是防御跨站请求伪造的基础方案,结合同源策略、Cookie的SameSite属性等防护措施,可以构建更完善的Web安全防护体系。

CSRF_Token跨站请求伪造Web安全Token验证修改时间:2026-06-27 20:54:56

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